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


1354

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


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

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

답변:


1838

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

표현식 x instanceof SomeClassfalseif x입니다 null.

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

"런타임에서 instanceof연산자 의 결과 trueRelationalExpression 의 값 이 아닌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연산자 의 결과 trueRelationalExpression 의 값 이 아니고 참조를 을 올리지 않고 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 Strings그가 될 수 있도록, 실제 값으로 대체됩니다 "" instanceof Stringnull 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.