Java编译器通过检查程序的源代码来验证类型安全,称为静态类型检测(Static checking)。无论是对于新手还是老鸟,静态检测能够避免程序员因为失误而引起的语法错误/类名或函数名错误/参数错误等,避免了将错误带入到运行阶段,可提高程序正确性/健壮性,例如:
//Error!
String five = 5;
编译器会给出以下信息:
test.java.2:incompatible types
found:int
required:java.lang.String
String five = 5;
编译器识别变量five的类型是String,但我们赋值是int,编译器便会给出警告(一般是红色波浪线)。
但是由于静态类型是在编译阶段前进行检查,难免会发生“误判”,下面举出一个例子:
class A {
A self{
return this;
}
public void printA() {
System.out.println("A");
}
}
class B extends A {
public void printB() {
System.out.println("B");
}
}
由于B继承了A的方法,调用new B().self()将返回B对象;但是由于self()方法被声明将返回A对象,所以编译器会认为只要使用self()方法,就会返回A对象。
这导致了一个问题:由于编译器在编译前会认为new B().self()会返回A对象,所以new B().self().printA();会被判定为合法的语句,而new B().self().printB();会被判定为非法语句。
//编译器认为是错误,但实际是正确的
new B.self().printB();
当然,程序员可以无视编译器的错误警告,但要是程序员也犯错了呢?所以为了避免编译器“误判”同时检测我们编写的代码是否正确,我们可以使用类型转换,例如上述例子中我们可以将new B().self().printB();改写为:
((B) new B().self()).printB();
此时,编译器就不会误判了。