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 C
とclass B
の間に関係はありませんが、obj instanceof A
の場合はコンパイラエラーが発生しますが、falseは発生しますか?
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
以下のクラス宣言で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
ステートメントを許可する理由です。