instanceof를 호출하기 전에 null 검사가 필요합니까?


1354

윌 null instanceof SomeClass반환 false또는 던져 NullPointerException?


또한 같은 유형의 null이 아닌 객체에서만 성공하도록 설계된 비교 또는 같거나 유사한 방법에 대해 '중요한'또는 최소한 '최고의'시작 (또는 매우 이른) 행으로 유용합니다. 한 줄로 '사실 사례'로부터 당신을 보호합니다. 적은 코드 = 적은 버그.

13
"이게 유용한가요?" 토론-나는 내 자신의 Java 코드를 작성한 적이 없다 (그래서 사양이 어디에 있는지 쉽게 알지 못하고 테스트를 컴파일하는 것이 매우 중요하지는 않지만), 나는 현재 수동으로 Java를 JavaScript로 변환하고있다. 내 코드는 null 참조에서 실패했으며 인터넷 검색을 통해 허용되는 답변을 볼 수 있습니다. 이는 예상 된 동작이며 암시 적 null 검사가 누락되었음을 나타냅니다. 제 경우에는 매우 유용합니다.
— Scott Mermelstein

답변:


1838

아니요, instanceof를 사용하기 전에 null 검사가 필요하지 않습니다.

표현식 x instanceof SomeClass은 falseif x입니다 null.

Java 언어 사양, 섹션 15.20.2, "유형 비교 연산자 instanceof"에서 :

"런타임에서 instanceof연산자 의 결과 true는 RelationalExpression 의 값 이 아닌null 경우 참조는 을 올리지 않고 ReferenceType 으로 캐스트 할 수 있습니다 ClassCastException. 그렇지 않으면 결과는 false" 입니다 . "

따라서 피연산자가 널이면 결과는 false입니다.


377
이 동작 은 현재 동작 이 보장 된 동작 과 같지 try it않기 때문에 보다 정확합니다 .
— Luke

3
이 질문에 개체 평등에 조슈아 블로흐의 장 동안 활동하기 시작 Effective Java- amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683
— 케빈 메러디스

17
특히, 항목 8에서 그는 equals () 메소드에서 하나의 instanceof 연산자가 두 가지 목적을 수행한다는 점에 주목합니다. 인수가 널이 아니며 올바른 유형인지 확인합니다. "... [S] o 별도의 null 검사가 필요하지 않습니다."
— Andy Thomas

2
@BenThurley-Java의 instanceof운영자는 거의 20 년 전에 릴리스 된 Java 1.0의 일부였습니다. 기존 코드를 손상시킬 수있는 방식으로 동작을 변경하는 것은 그리 큰 비용이 들지 않는 이점이 없습니다. 20 년 전, 인수가 캐스트 될 수 있거나 널 (null) 인수에 대한 예외를 던지는 경우 true를 리턴하기위한 인수가있을 수 있습니다. 그러나 이러한 정의에는 별도의 null 검사가 필요했습니다.
— Andy Thomas

3
@BenThurley-동작은 과거와 현재의 Java 사양에 의해 보장됩니다. 누가의 요점은 현재의 보장 된 행동을 결정할 때 실험의 한계를 다루고 있다고 생각합니다.
— Andy Thomas

267

instanceof반환 할 첫 번째 피연산자로 null 참조를 사용 합니다 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

런타임시 instanceof연산자 의 결과 true는 RelationalExpression 의 값 이 아니고 참조를 을 올리지 않고 ReferenceTypenull 으로 캐스트 할 수있는 경우 입니다. 그렇지 않으면 결과는 입니다.ClassCastExceptionfalse

API / 클래스 #isInstance (오브젝트)

이 Class객체가 인터페이스를 나타내는 경우,이 메소드는 true, 지정된 Object인수 의 클래스 또는 슈퍼 클래스 가이 인터페이스를 구현 하고있는 경우를 돌려줍니다 . false그렇지 않으면 반환 합니다. 이 Class객체가 원시적 형을 나타내는 경우 ,이 메소드는를 리턴합니다 false.


혼란스러운 종류. s는 "String s"라고 표시되므로 String이고, s는 null이므로 String이 아닙니다. 그래서 대체 뭐야?
— Kai Wang

1
@KaiWang s은 객체 참조 변수 일뿐 입니다. 실제로 존재하는 객체 ( "")를 참조하거나 null리터럴 참조를 참조 할 수 있습니다.
— Jin Kwon

여전히 혼란 스러워요. s는 이제 null 일 수 있지만 나중에 String 인스턴스 만 가리킬 수 있습니다. 정수와 같이 가리킬 수 없습니다. 그래서 그것은 여전히 ​​일종의 문자열입니다. 그다지 이해가되지 않습니다 ...
— Kai Wang

@KaiWang 변수 유형을 실제 객체의 유형과 혼동하고 있습니다. 변수는 인스턴스가 아닙니다. 그들은 단지 포인터 일뿐입니다. null변수가 가리키는 변수에 관계없이 문자열 데이터가 아닙니다. 예를 들어와 s instanceof String같지 않습니다 field.getType().equals(String.class).
— Matthew 읽기

@KaiWang 당신은 전화에서 상상해야 s instanceof String이 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.)


추신 : 고용하는 경우, 이것을 면접 질문으로 사용하지 마십시오. :디


7

없음 . Java 리터럴 null은 어떤 클래스의 인스턴스도 아닙니다. 따라서 클래스 의 인스턴스가 될 수 없습니다 . instanceof 중 반환 false또는true 때문에 <referenceVariable> instanceof <SomeClass>반환 false할 때 referenceVariable값이 null입니다.


5
그 설명은 이상하게 원형으로 들리지만 ... 나는 당신이 무슨 뜻인지 안다 :-)
— Kris

의견에 대한 @Kris ty 나는 당신이 의미하는 것을 얻었습니다 :). 답변을 약간 편집했습니다 :).
— 개발자 Marius Žilėnas

1

instanceof운영자는 명시 적으로 필요하지 않습니다 null그것은 포기하지 않는 한, 검사를 NullPointerException피연산자 인 경우 null.

런타임시, instanceof관계식의 값이 아니고 null클래스 캐스트 예외를 발생시키지 않고 참조를 참조 유형으로 캐스트 할 수있는 경우 연산자 결과 는 true 입니다.

피연산자가 null이면 instanceof연산자가 반환 false되므로 명시적인 null 검사가 필요하지 않습니다.

아래 예를 고려하십시오.

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");
         }  
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.