Чи потрібна нульова перевірка перед викликом instanceof?


1354

Буде чи null instanceof SomeClassповернутися falseабо кинути NullPointerException?


Це також "важливий" або, принаймні, дуже корисний як початковий (або дуже ранній) рядок "найкращої практики" для будь-якого методу "Порівняти" або "Рівний" або подібного методу, призначеного для досягнення успіху лише на ненульових об'єктах одного типу, і оберігає вас від "дурних справ" в одному рядку. менше коду = менше помилок.

13
Зважити на тему "чи це корисно?" дебати - Я ніколи не писав власний код Java (тому не легко знати, де є характеристики, і складати тест було б дуже нетривіально), але наразі я перетворюю Java в JavaScript. Мій код не вдався до нульової посилання, і гуглюючи це, я дозволив побачити прийняту відповідь, яка підтвердила, що це очікувана поведінка і що я пропускав неявну нульову перевірку. Дуже корисно, в моєму випадку.
Скотт Мермельштайн

Відповіді:


1838

Ні, нульова перевірка не потрібна перед використанням instanceof.

Вираз x instanceof SomeClassє, falseякщо xє null.

З специфікації мови Java, розділ 15.20.2, "Тип оператора порівняння екземпляраofof" :

"Під час виконання результатом instanceofоператора є, trueякщо значення RelationalExpression не є,null і посилання може бути передано на ReferenceType без підвищення а ClassCastException. Інакше результат є false."

Отже, якщо операнд недійсний, результат хибний.


377
Ця відповідь правильніша, ніж try itтому, що поточна поведінка не є такою ж, як гарантована поведінка .
Лука

3
Це питання виникає під час глави Джошуа Блоха про рівність об'єктів у Effective Java- amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683
Кевін Мередіт

17
Зокрема, у пункті 8 він зазначає, що в методах рівних () один екземпляр оператора виконує дві цілі - він перевіряє, що аргумент є однозначним і правильним. "... [S] o вам не потрібна окрема нульова перевірка."
Енді Томас

2
@BenThurley - instanceofОператор Java був частиною Java 1.0, випущеної майже 20 років тому. Зміна поведінки зараз таким чином, що порушить існуючий код, малоймовірна, відсутня якась вигода, яка перевершує величезну вартість. Двадцять років тому, можливо, могли бути аргументи для повернення істини, якщо аргумент може бути подано, або викидання виключення з нульового аргументу. Але ці визначення потребували б окремої нульової перевірки.
Енді Томас

3
@BenThurley - поведінку гарантують специфікації Java минулі та теперішні. Я думаю, що точка Луки стосується обмежень експериментування у визначенні гарантованої поведінки сьогодення.
Енді Томас

267

Використання нульової посилання як перший операнд для instanceofповернення false.


268
(А зараз на пошук цього питання в Google потрібно 10 секунд)
PL_kolek

73

Справді, дуже гарне запитання. Я просто спробував для себе.

public class IsInstanceOfTest {

    public static void main(final String[] args) {

        String s;

        s = "";

        System.out.println((s instanceof String));
        System.out.println(String.class.isInstance(s));

        s = null;

        System.out.println((s instanceof String));
        System.out.println(String.class.isInstance(s));
    }
}

Друкує

true
true
false
false

JLS / 15.20.2. Типи Оператор порівняння типу

Під час виконання результатом instanceofоператор є, trueякщо значення RelationalExpression не є nullі посилання може бути передане на ReferenceType без підвищення a ClassCastException. Інакше результат є false.

API / клас # isInstance (об’єкт)

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


Вигляд заплутаний. s - це рядок, тому що в ній написано "String s", s - це не String, оскільки вона є null. Так що, чорт забирає?
Кай Ван

1
@KaiWang s- просто змінна посилання на об'єкт. Він може посилатися на фактично існуючий об'єкт ( "") або може посилатися на (the) nullбуквальне посилання.
Джин Квон

Я все ще плутаюсь. s може бути нульовим зараз, але його можна вказати лише на екземпляр String пізніше. Його не можна вказувати, як, наприклад, на Ціле число. Так що це все-таки рід Струни, навіть це нуль. Просто не має великого сенсу ...
Кай Ван,

@KaiWang Ви плутаєте тип змінної з типом фактичного об'єкта. Змінні не є екземплярами; вони фактично просто покажчики. nullне є рядковими даними, незалежно від того, яка змінна вказує на нього. s instanceof Stringне те саме, що field.getType().equals(String.class), наприклад.
Матвій

@KaiWang ви повинні уявити, що у виклику s instanceof Stringкоманда get sзаміняється фактичним значенням, так що це стане "" instanceof Stringі null instanceof String. Думати про це так, можливо, має більше сенсу.
Timo Türschmann


16

Так само, як ласощі :

Навіть повернеться .(((A)null)instanceof A)false


(Якщо набір клавіш nullздається дивним, іноді доводиться це робити, наприклад, у таких ситуаціях:

public class Test
{
  public static void test(A a)
  {
    System.out.println("a instanceof A: " + (a instanceof A));
  }

  public static void test(B b) {
    // Overloaded version. Would cause reference ambiguity (compile error)
    // if Test.test(null) was called without casting.
    // So you need to call Test.test((A)null) or Test.test((B)null).
  }
}

Тож Test.test((A)null)надрукуємо a instanceof A: false.)


PS: Якщо ви приймаєте на роботу, будь ласка, не використовуйте це як питання співбесіди. : D


7

Ні . Java literal nullне є примірником жодного класу. Тому він не може бути екземпляром жодного класу. instanceof повертає або, falseабоtrue тому <referenceVariable> instanceof <SomeClass>повертає, falseколи referenceVariableзначення є нульовим.


5
Це пояснення звучить дивно кругло ... але я знаю, що ви маєте на увазі :-)
Кріс,

@Kris ty для коментаря я зрозумів, що ти маєш на увазі :). Відповідь трохи відредагували :).
розробник Marius Žilėnas

1

instanceofОператор не потребує в явних nullперевірок, так як він не кидати , NullPointerExceptionякщо операнд null.

Під час виконання результат instanceofоператора є істинним, якщо значення реляційного вираження відсутнє nullі посилання може бути передано на тип посилання без підвищення виключення класу.

Якщо операнд є null, instanceofоператор повертається, falseа значить, явні перевірки нуля не потрібні.

Розглянемо нижченаведений приклад,

public static void main(String[] args) {
         if(lista != null && lista instanceof ArrayList) {                     //Violation
                System.out.println("In if block");
         }
         else {
                System.out.println("In else block");
         }
}

Правильне використання instanceof, як показано нижче,

public static void main(String[] args) {
      
         if(lista instanceof ArrayList){                     //Correct way
                  System.out.println("In if block");
         }
            else {
                 System.out.println("In else block");
         }  
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.