Подтвердить что ты не робот

Почему переменная класса не может быть передана instanceof?

Почему этот код не компилируется?

    public boolean isOf(Class clazz, Object obj){
        if(obj instanceof clazz){
            return true;
        }else{
            return false;
        }
    }

Почему я не могу передать переменную класса в instanceof?

4b9b3361

Ответ 1

Оператор instanceof работает с ссылочными типами, например Integer, а не с объектами, например new Integer(213). Вероятно, вы хотите что-то вроде

clazz.isInstance(obj)

Боковое примечание: ваш код будет более кратким, если вы напишете

public boolean isOf(Class clazz, Object obj){
    return clazz.isInstance(obj)
}

Не уверен, что вам нужен метод больше.

Ответ 2

instanceof может использоваться только с явными именами классов (указанными во время компиляции). Чтобы выполнить проверку времени выполнения, вы должны сделать:

clazz.isInstance(obj)

Это имеет небольшое преимущество перед clazz.isAssignableFrom(..), поскольку имеет дело с случаем obj == null лучше.

Ответ 3

Во-первых, instanceof требует, чтобы операнд справа являлся фактическим классом (например, obj instanceof Object или obj instanceof Integer), а не переменной типа Class. Во-вторых, вы сделали довольно распространенную ошибку новичков, которую вы действительно не должны делать... следующий шаблон:

if ( conditional_expression ){
    return true;
} else{
    return false;
}

Вышеуказанное может быть реорганизовано в:

return conditional_expression;

Вы всегда должны выполнять этот рефакторинг, так как он исключает избыточную if... else. Аналогично, выражение return conditional_expression ? true : false; рефакторизуется с тем же результатом.

Ответ 4

Как уже упоминалось, вы не можете передать переменную класса в instanceof, потому что переменная класса ссылается на экземпляр объекта, тогда как правая часть instanceof должна быть типом. То есть instanceof не означает, что "y - это экземпляр объекта x", это означает, что "y является экземпляром типа X". Если вы не знаете разницу между объектом и типом, рассмотрите:

Object o = new Object();

Здесь тип Object, а o - ссылка на экземпляр объекта с этим типом. Таким образом:

if(o instanceof Object)

но

if(o instanceof o)

не потому, что o в правой части есть объект, а не тип.

Более конкретно для вашего случая, экземпляр класса не является типом, это объект (который создается для вас JVM). В вашем методе Class - это тип, но clazz - это объект (ну, ссылка на объект)

Вам нужен способ сравнения объекта с объектом класса. Оказывается, это популярно, поэтому это предоставляется вам как метод объекта класса: isInstance().

Вот Java Doc для isInstance, который объясняет это лучше:

public boolean isInstance(Object obj)

Определяет, соответствует ли указанный объект совместимости с объект, представленный этим классом. Этот метод является динамическим эквивалент оператора экземпляра Java language. Метод возвращает true, если указанный аргумент Object не равен null и может быть приведение к ссылочному типу, представленному этим объектом класса, без повышение класса ClassException. В противном случае он возвращает false.

В частности, если этот объект класса представляет объявленный класс, это метод возвращает true, если указанный аргумент Object является экземпляром представляемый класс (или любой из его подклассов); он возвращает false в противном случае. Если этот объект класса представляет класс массива, этот метод возвращает true, если указанный аргумент Object может быть преобразован в объект класса массива путем преобразования идентичности или расширения обратное преобразование; он возвращает false в противном случае. Если этот объект класса представляет собой интерфейс, этот метод возвращает true, если класс или любой суперкласс заданного аргумента объекта реализует этот интерфейс; он возвращает false в противном случае. Если этот объект класса представляет собой примитивный тип, этот метод возвращает false.

Параметры: obj - объект для проверки Возвращает: true, если obj является экземпляром этого класса
Поскольку: JDK1.1