Чому змінну “Class” не можна передати instanceof?


89

Чому цей код не компілюється?

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

Чому я не можу передати змінну класу instanceof?

Відповіді:


131

instanceofОператор працює на посилальних типів, як Integer, а не на об'єкти, як new Integer(213). Ви, мабуть, хочете щось подібне

clazz.isInstance(obj)

Примітка: ваш код буде більш стислим, якщо ви пишете

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

Не зовсім впевнений, що вам більше потрібен метод.


Я знаю, що код абсолютно марний, я просто хочу продемонструвати свою плутанину :)
eric2323223

6
Integerце НЕ літерал класу. Integer.classбуде літералом класу (див. § 15.8.2 JLS: java.sun.com/docs/books/jls/third_edition/html/… ). instanceofОператор приймає «ReferenceType» (він же ім'я типу) , як зазначено § 15.20.2 з JLS: java.sun.com/docs/books/jls/third_edition/html / ...
Joachim Sauer

3
Я б використовував, clazz.isInstance(obj)оскільки об’єкт уже надано.
Donal Fellows

13

instanceofможе використовуватися лише з явними назвами класів (зазначених під час компіляції). Для того, щоб перевірити час виконання , вам слід виконати:

clazz.isInstance(obj)

Це має невелику перевагу в порівнянні clazz.isAssignableFrom(..)з тим, що воно вирішує справу obj == nullкраще.


5

Як вже згадували інші, ви не можете передати змінну класу, 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. Метод повертає true, якщо вказаний аргумент Object не є нульовим і може бути переданий до посилального типу, представленого цим об'єктом Class, не викликаючи ClassCastException. Інакше повертає false.

Зокрема, якщо цей об'єкт Class представляє оголошений клас, цей метод повертає true, якщо вказаний аргумент Object є екземпляром представленого класу (або будь-якого з його підкласів); в іншому випадку вона повертає false. Якщо цей об'єкт Class представляє клас масиву, цей метод повертає true, якщо вказаний аргумент Object може бути перетворений в об'єкт класу масиву шляхом перетворення ідентичності або розширення перетворення посилання; в іншому випадку вона повертає false. Якщо цей об'єкт Class представляє інтерфейс, цей метод повертає true, якщо клас або будь-який суперклас зазначеного аргументу Object реалізує цей інтерфейс; в іншому випадку вона повертає false. Якщо цей об'єкт Class представляє примітивний тип, цей метод повертає false.

Параметри: obj - об'єкт для перевірки
Повертає: true, якщо obj є екземпляром цього класу
Since: JDK1.1


3

По-перше, instanceofвимагає, щоб операнд праворуч був фактичним класом (наприклад, obj instanceof Objectабо obj instanceof Integer), а не змінною типу Class. По-друге, ви допустили досить поширену помилку новачка, якої вам справді не слід робити ... таку схему:

if ( умовне_вираз ) {
    повернути істинно;
} ще {
    повернути false;
}

Вищевказане можна перетворити на:

повернути умовне_вираз ;

Ви завжди повинні виконувати цей рефакторинг, оскільки він усуває зайвий оператор if ... else. Подібним чином вираз можна відновити до того самого результату.return conditional_expression ? true : false;


2
Це не помилка. Можливо, незграбний, але цілком нормально. Можливо, вам потрібен додатковий код перед поверненням в осяжному майбутньому ...
Неймовірний
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.