Почему переменная класса не может быть передана instanceof?
Почему этот код не компилируется?
public boolean isOf(Class clazz, Object obj){
if(obj instanceof clazz){
return true;
}else{
return false;
}
}
Почему я не могу передать переменную класса в instanceof
?
Ответы
Ответ 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