web-dev-qa-db-ja.com

「instanceof」演算子は、インターフェースとクラスに対して異なる動作をします

Javaのinstanceof演算子の次の動作について知りたいのですが。

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 Cclass Bの間に関係はありませんが、obj instanceof Aの場合はコンパイラエラーが発生しますが、falseは発生しますか?

88
Ajay Sharma

Javaには複数のクラスの継承がないため、コンパイル時にobj型のBオブジェクトはAのサブタイプにはなり得ないことが絶対にわかっています。一方、たとえばこの場合、インターフェイス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
127
Tagir Valeev

以下のクラス宣言で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 {
}

そうでない場合、Testfinalとして宣言されていない場合、Testのサブクラスがインターフェースを実装する可能性があります。そして、それがコンパイラがこの場合test instanceof Foobarステートメントを許可する理由です。

1