Java 使用instanceof进行编译时检查
对于下面的代码Java 使用instanceof进行编译时检查,java,javac,instanceof,Java,Javac,Instanceof,对于下面的代码 package java_instanceof; /* * * Object I0 * I1 I2 ^ \ . ^ * . . | \ . |
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
如何能够引发编译时错误不兼容的条件操作数类型
?编译时是否知道完整的类层次结构?是!当然,层次结构可能是“实现”或“扩展”等,在编译时是已知的
如果没有这些检查,即使在试图编写代码的关系树中进一步编程,也无法利用OOPS
考虑一个对象类本身的例子,如果对象不是所有类的父类,您可能无法重写基本上来自对象类的toString()、hashcode()、clone()方法。因此,您可以在任何IDE的intellisence中获得这些方法,因此这些方法甚至在执行之前就已经预编译了。是和否。当然,编译文件及其导入的文件中所有类和接口的类层次结构在编译时是已知的。但是,在运行时可能会有额外的类和接口 但是,在您的情况下,
C3
和B
都是类,可用信息足以确定C3
永远不能引用B
的实例,B
永远不能引用C3
的实例。这种情况是因为类继承自单个超类(或者,在对象的情况下,不继承)超类
有了接口,情况就不同了。以下片段不会导致编译时错误:
I1 i1 = ... ;
boolean v = i1 instanceof B;
因为有人可能会声明B
的子类,该子类也实现了I1
是,编译器首先查看方法的词法层次结构,然后查看类层次结构,最后查看全局范围。有关编译器如何工作的更多相关信息,请参阅Keith Cooper的《设计编译器》一书-方法和类调用主题
对于您的第一个问题,您可能会发现这很有帮助 “类层次结构在编译时已知吗?”-嗯,是的,您期望什么?您可以在向上面添加另一个classd
时阅读,classd扩展了B实现了I1{};B=新的D();值=I2的b实例代码>这应该在运行时给出false
。但为什么编译器在编译时无法找到不兼容的操作数类型
错误?要决定是否显示编译器错误,编译器只查看instanceof
运算符的类型。有人可能会定义D
的子类,该子类也实现了I2
,因此b实例的I2
不会导致编译器错误。所以,基本点是多个子类可以实现接口,所以当您提供接口类型作为正确的操作数时,编译器保持安静,对吗?