使用instanceof编译时间检查

时间:2015-07-22 08:38:25

标签: java javac instanceof

对于以下代码,

package java_instanceof;

        /*
         *                   
         *                     Object                  I0 
         *   I1    I2         ^        \              . ^
         *     .    .         |         \           .   |
         *       .   .        |          \ ______ .     |
         *         .  .       C1          |__B___|     I3
         *           . .     /                      .        
         *             ..   /                   .            
         *               C2                  .              
         *                ^               .                                    
         *                |            .                   
         *                |        .                      
         *                |    .
         *                C3 
         *                                           
         */ 

interface I0{}; interface I1{}; interface I2 {};
interface I3 extends I0{};

class C1{}; class B implements I0{};
class C2 extends C1 implements I1, I2 {}
class C3 extends C2 implements I3 {}

public class Example {

    public static void main(String[] args) {


        Object o;  Object[]  oa;
        I0    i0;  I0[]      i0a;
        I1    i1;  I1[]      i1a; 
        I2    i2;  I2[]      i2a;
        I3    i3;  I3[]      i3a;
        C1    c1;  C1[]      c1a;
        C2    c2;  C2[]      c2a;
        C3    c3;  C3[]      c3a;
        B     b;   B[]        ba;

        //Compile time check
        boolean value1 = c3 instanceof B;  //compile time check error
        boolean value2 = b instanceof C3;  // compile time check error


    }

}

作为初学者,我想知道,javac如何能够引发编译时错误Incompatible conditional operand type?在编译时是否知道完整的类层次结构?

3 个答案:

答案 0 :(得分:2)

是和否。当然,编译文件中所有类和接口的类层次结构以及由它导入的文件在编译时都是已知的。但是,在运行时可能会有其他类和接口。

但是,在您的情况下,C3B都是类,然后可用信息足以确定c3永远不会引用B的实例,b永远不能引用C3的实例。这是因为类继承自单个(或者,在Object,没有)超类的情况下。

对于接口,情况有所不同。以下片段不会导致编译时错误:

I1 i1 = ... ;
boolean v = i1 instanceof B;

因为某人可能声明了B的子类,该子类也实现了I1

答案 1 :(得分:0)

!当然,层次结构,可能是“实现”或“扩展”等在编译时是已知的。

如果没有这些检查,即使进一步编程到您尝试编码的关系树中,也无法利用OOPS。

考虑一个 Object 类本身的示例,如果Object不是所有类的父类,则可能无法覆盖 toString(),hashcode(),clone( )方法基本上来自Object Class。因此,您可以在任何IDE的智能中获得这些方法,因此这些方法在执行之前已经预编译。

答案 2 :(得分:0)

是的,编译器首先查看方法的词法层次结构,然后查看类层次结构,最后查看全局范围。有关编译器如何工作的更多相关信息,您可以参考Book" Engineering a Compiler"作者:Keith Cooper-方法和类调用主题。

对于您的第一个问题,您可能会发现此http://codereply.com/answer/42s61x/instanceof-incompatible-conditional-operand-types.html有用。