«1. Обзор

В этой статье мы рассмотрим различные способы поиска класса объекта в Java.

2. Использование метода getClass()

Первый метод, который мы проверим, это метод getClass().

Во-первых, давайте посмотрим на наш код. Мы напишем класс User:

public class User {
    
    // implementation details

}

Теперь давайте создадим класс Lender, который расширяет User:

public class Lender extends User {
    
    // implementation details

}

Точно так же мы создадим класс Borrower, который также расширяет User:

public class Borrower extends User {
    
    // implementation details

}

~ ~~ Метод getClass() просто возвращает класс времени выполнения объекта, который мы оцениваем, поэтому мы не рассматриваем наследование.

Как мы видим, getClass() показывает, что класс нашего объекта кредитора имеет тип Lender, но не тип User:

@Test
public void givenLender_whenGetClass_thenEqualsLenderType() {
    User lender = new Lender();
    assertEquals(Lender.class, lender.getClass());
    assertNotEquals(User.class, lender.getClass());
}

3. Использование метода isInstance()

При использовании isInstance() мы проверяем, относится ли объект к определенному типу, и по типу мы говорим либо о классе, либо об интерфейсе.

Этот метод вернет true, если наш объект, отправленный в качестве аргумента метода, пройдет тест IS-A для класса или типа интерфейса.

Мы можем использовать метод isInstance() для проверки класса объекта во время выполнения. Кроме того, isInstance() также обрабатывает автоупаковку.

Если мы проверим следующий код, мы обнаружим, что код не компилируется:

@Ignore
@Test
public void givenBorrower_whenDoubleOrNotString_thenRequestLoan() {
    Borrower borrower = new Borrower();
    double amount = 100.0;
        
    if(amount instanceof Double) { // Compilation error, no autoboxing
        borrower.requestLoan(amount);
    }
        
    if(!(amount instanceof String)) { // Compilation error, incompatible operands
        borrower.requestLoan(amount);
    }
        
}

Давайте проверим автоупаковку в действии, используя метод isInstance():

@Test
public void givenBorrower_whenLoanAmountIsDouble_thenRequestLoan() {
    Borrower borrower = new Borrower();
    double amount = 100.0;
        
    if(Double.class.isInstance(amount)) { // No compilation error
        borrower.requestLoan(amount);
    }
    assertEquals(100, borrower.getTotalLoanAmount());
}

Теперь давайте попробуем оценить наш объект во время выполнения:

@Test
public void givenBorrower_whenLoanAmountIsNotString_thenRequestLoan() {
    Borrower borrower = new Borrower();
    Double amount = 100.0;
        
    if(!String.class.isInstance(amount)) { // No compilation error
        borrower.requestLoan(amount);
    }
    assertEquals(100, borrower.getTotalLoanAmount());
}

Мы также можем использовать isInstance(), чтобы проверить, может ли объект быть приведен к другому классу перед его приведением:

@Test
public void givenUser_whenIsInstanceOfLender_thenDowncast() {
    User user = new Lender();
    Lender lender = null;
        
    if(Lender.class.isInstance(user)) {
        lender = (Lender) user;
    }
        
    assertNotNull(lender);
}

Когда мы используем isInstance () мы защищаем нашу программу от попыток нелегального приведения вниз, хотя использование оператора instanceof в этом случае будет более плавным. Давайте проверим это дальше.

4. Использование оператора instanceof

Подобно методу isInstance(), оператор instanceof возвращает значение true, если оцениваемый объект принадлежит к данному типу — другими словами, если наш объект, указанный слева сторона оператора проходит тест IS-A для класса или типа интерфейса с правой стороны.

Мы можем оценить, является ли объект Lender типом Lender и типом User:

@Test
public void givenLender_whenInstanceOf_thenReturnTrue() {
    User lender = new Lender();
    assertTrue(lender instanceof Lender);
    assertTrue(lender instanceof User);
}

Чтобы получить более подробное представление о том, как работает оператор instanceof, мы можем найти дополнительную информацию в нашей статье об операторе Java instanceOf.

5. Заключение

В этой статье мы рассмотрели три разных способа нахождения класса объекта в Java: метод getClass(), метод isInstance() и оператор instanceof.

Как обычно, полные примеры кода доступны на GitHub.