Java ';instanceof';运算符对于接口和类的行为不同

Java ';instanceof';运算符对于接口和类的行为不同,java,class,inheritance,interface,instanceof,Java,Class,Inheritance,Interface,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 in

我想知道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
    }
}

为什么会这样?
接口C
类B
之间没有关系,但是它给出了false,而在A的
obj实例的情况下它给出了编译器错误?

因为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  
    }
}

因此,仅查看C的
obj实例
表达式编译器无法预先判断它是真是假,但查看A的
obj实例
它知道这总是假的,因此没有意义,并帮助您防止错误。如果仍希望在程序中执行此无意义的检查,则可以向
对象添加显式强制转换

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

通过在下面的类声明中使用
final
修饰符,可以保证不存在可能实现接口
Foobar
Test
子类。在这种情况下,
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
的子类实现了该接口。这就是为什么编译器在这种情况下允许语句
testinstanceof Foobar

无意义检查的另一种风格是使用
a.class.isAssignableFrom(obj.getClass())
我对你的解释感到有点困惑,你说
Java没有多类继承
是的,我同意,但在这种情况下它是如何应用的,因为B或A都不扩展任何东西,所以为什么在这里有多个继承。如果你能解释一下,那会很有帮助吗?@codegasmer Late回答:如果Java允许一个类从多个其他类继承类,然后可以执行“类D扩展A,B”或类似操作,然后执行“B obj=new D()”,并使原始问题中的“obj instanceof A”编译(而它目前没有编译)——事实上它最好编译,因为它的计算结果应该为true。但是如果不允许任何东西同时是B和A,那么obj被定义为B类型的表达式“obj instanceof A”可以被合理地认为是无意义的。“如果你仍然想要这个无意义的检查”-它不需要是无意义的,就像这些类来自其他库/框架一样,您有可能在运行时使用不同的版本,其中
B扩展了A
。在我的生活中,我实际上需要做一些奇怪的检查和强制转换,如运行时中的
(A)(Object)b
,这实际上是可能的。注意:如果您将其更改为
Object obj=new b()
,它可以编译。编译器错误告诉你什么?如果
B类
final
,那么
obj实例C
也不会编译,因为如果
B
可以没有子类型,那么它保证与
C
无关。