'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 2015

1
コンパイラエラーは何を示していますか?
karfau

if もコンパイルされません。サブタイプがない場合class Bfinalobj instanceof CとはB無関係であることが保証されているためCです。
jaco0646 2016年

回答:


127

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

1
意味のないチェックのもう1つの特徴は、使用することですA.class.isAssignableFrom(obj.getClass())
David Ehrmann

Java has no multiple class inheritanceはい、同意しますが、BとAのどちらも拡張を行わないため、ここで多重継承が行われるので、この方法でどのように適用されるのかと少し混乱しています。
codegasmer

@codegasmer遅い答え:Javaがクラスに他の複数のクラスからの継承を許可した場合、「クラスDがA、Bを拡張する」などを実行し、「B obj = new D()」を実行して、「obj元の質問のinstanceof A "はコンパイルされます(現在はそうではありません)。実際には、trueと評価されることが予想されるため、コンパイルした方がよいでしょう。しかし、BとAの両方が許可されていない場合、objがタイプBとして定義されている式 "obj instanceof A"は、無意味であると合理的に見なすことができます。
mjwach

「この無意味なチェックが必要な場合」-このクラスが他のライブラリ/フレームワークからのものであるかのように、無意味である必要はありませんB extends A。実行時に異なるバージョンを使用する可能性があります。私の人生(A)(Object)bでは、実行時と同じように奇妙なチェックとキャストを実際に行う必要がありました。
GotoFinal 2018

1

final以下のクラス宣言で修飾子を使用することによりTest、インターフェースを実装する可能性のあるのサブクラスが存在しないことが保証されますFoobar。この場合は、あることは明らかであるTestとは、Foobar相互に互換性がありません。

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.