'instanceof'연산자는 인터페이스와 클래스에 대해 다르게 작동합니다.


88

instanceofJava에서 연산자의 다음 동작에 대해 알고 싶습니다 .

interface C {}

class B {}

public class A {
    public static void main(String args[]) {
        B obj = new B();
        System.out.println(obj instanceof A);      //Gives compiler error
        System.out.println(obj instanceof C);      //Gives false as output
    }
}

왜 그래야만하지? 이 사이에 아무 관계 없다 interface C하고 class B, 그러나의 그것은 경우에 반면 거짓 제공 obj instanceof A은 컴파일러 오류를 준다?


12
참고 :로 변경 Object obj = new B()하면 컴파일됩니다.
user253751 jul.

1
컴파일러 오류는 무엇을 알려 줍니까?
karfau jul.

경우 class B입니다 final다음 obj instanceof C경우 때문에 어느 컴파일되지 않습니다 B더 하위 유형을 가질 수 없습니다, 다음은 관련이없는 것으로 보장된다 C.
jaco0646

답변:


127

Java에는 다중 클래스 상속이 없기 때문에 컴파일 중에 obj유형의 객체가의 B하위 유형이 될 수 없다는 것이 절대적으로 알려져 있습니다 A. 반면에 다음과 같이 interface의 하위 유형이 될 수 있습니다 C.

interface C {}

class B {}

class D extends B implements C {}

public class A {
    public static void main(String args[]) {
        B obj = new D();
        System.out.println(obj instanceof C);      //compiles and gives true as output  
    }
}

따라서 obj instanceof C표현식 컴파일러 만 보면 그것이 참인지 거짓인지 미리 알 수 없지만, obj instanceof A그것을 보면 이것이 항상 거짓이라는 것을 알고 있으므로 의미가 없으며 오류를 방지하는 데 도움이됩니다. 프로그램에서이 의미없는 검사를 계속하려면에 명시 적 캐스팅을 추가 할 수 있습니다 Object.

System.out.println(((Object)obj) instanceof A);      //compiles fine

1
의미없는 검사의 또 다른 맛을 사용하는 것입니다A.class.isAssignableFrom(obj.getClass())
데이비드 Ehrmann

나는 당신이 Java has no multiple class inheritance동의 한다고 말한 당신의 설명과 약간 혼란 스럽습니다. 하지만 B 또는 A가 확장되지 않기 때문에이 경우 어떻게 적용되는지 왜 여기에서 다중 상속이 필요한지 설명 할 수 있다면 도움이 될까요?
codegasmer

@codegasmer 후기 답변 : Java가 한 클래스가 다른 여러 클래스에서 상속하도록 허용했다면 "클래스 D는 A, B를 확장합니다"또는 그런 다음 "B obj = new D ()"를 수행하고 "obj instanceof A "는 원래 질문 컴파일에서 (현재는 그렇지 않지만) 사실로 평가 될 것으로 예상되기 때문에 더 나은 컴파일을 가졌습니다. 그러나 단순히 B와 A가 둘 다 허용되지 않는 경우 obj가 B 유형으로 정의 된 "obj instanceof A"라는 표현은 합리적으로 무의미한 것으로 간주 될 수 있습니다.
mjwach

"이 의미없는 검사를 계속하려면"-이 클래스가 다른 라이브러리 / 프레임 워크에서 가져온 것처럼 의미가 없을 필요는 없습니다 B extends A. 런타임에 다른 버전을 사용할 가능성이 있습니다 . 제 인생에서 저는 실제로 (A)(Object)b런타임에서 사실이 될 수있는 것처럼 이상한 검사와 캐스트를해야 했습니다.
GotoFinal

1

final아래 클래스 선언에서 한정자 를 사용 Test하면 인터페이스를 구현할 수있는의 하위 클래스가있을 수 없음을 보장합니다 Foobar. 이 경우 TestFoobar서로 호환되지 않음 이 분명합니다 .

public final class Test {

    public static void main(String[] args) {
        Test test = new Test();
        System.out.println(test instanceof Foobar); // Compiler error: incompatible types
    }
}

interface Foobar {
}

그렇지 Test않고 선언되지 않은 경우 final의 서브 클래스가 Test인터페이스 를 구현할 수 있습니다. 이것이 컴파일러 test instanceof Foobar가이 경우 명령문 을 허용하는 이유 입니다.

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