接口和类的'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,但是它给出false,而如果obj instanceof A给出编译器错误?


12
注意:如果将其更改为Object obj = new B(),则会进行编译。
user253751

1
编译器错误告诉您什么?
karfau

如果class B是,finalobj instanceof C也不会编译,因为如果B没有子类型,则可以保证与无关C
jaco0646 '16

Answers:


127

由于Java没有多类继承,因此在编译期间绝对知道objtype的对象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())
David Ehrmann

我对您的解释感到困惑,您说Java has no multiple class inheritance是的,但我同意,但是由于B或A都没有扩展任何含义,因此在这种情况下如何使用它,那么为什么要在这里进行多重继承。
codegasmer

@codegasmer最新答案:如果Java允许一个类从多个其他类继承,则可以执行“ D类扩展A,B”或类似的操作,然后执行“ B obj = new D()”,然后使“ obj原始问题中的A的“ instanceof A”(尽管当前尚未编译)—实际上,它的编译效果更好,因为可以期望它的评估结果为true。但是,如果根本不允许任何东西都同时为B和A,则可以合理地认为其中obj被定义为B类型的表达式“ obj instanceof A”可以被认为是荒谬的。
mjwach '16

“如果您仍然希望进行无意义的检查”-不必无意义,就好像该类来自其他库/框架一样,那么您有可能在运行时使用不同版本B extends A。在我的一生中,我实际上需要做一些奇怪的检查和转换,就像(A)(Object)b在运行时一样,这实际上是有可能的。
GotoFinal

1

通过final在下面的类声明中使用修饰符,可以确保不会存在的子类Test,而该子类可以实现interface 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在这种情况下允许该语句的原因。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.