简易Java(04):Java如何进行静态类型检查?
维基百科上对“静态类型检查”和“动态类型检查”的介绍如下:
静态类型检查是一个基于程序源代码分析来确保程序类型安全的过程。
动态类型检查是一个在运行时检查程序类型安全的过程。
Java语言在编译时使用静态类型检查来分析程序。如果有类型错误,则报错。基本思想是不要让类型错误在运行时发生。通过下面的例子,可以更好地理解Java中静态类型检查的工作原理。
1、代码示例
假设我们有如下两个类,A
和B
。并且,B
继承A
。
/** * Coder: D瓜哥,http://www.diguage.com/ */ class A { A me() { return this; } public void doA() { System.out.println("Do A"); } } class B extends A { public void doB() { System.out.println("Do B"); } }
首先,new B().me()
返回什么?一个A
对象?还是一个B
对象?
me()
方法确实声明返还一个A
对象。所以,在编译的时候,编译器仅仅能看到它返还了一个A
对象。但是,在运行时它却返还的是一个B
对象,因为B
类继承了A
类的方法,然后返还了this
(自身对象)。
2、静态类型是如何工作的?
下面这行代码是不合法的,即使调用对象确实是B
对象。问题就在于它的引用类型是A
。在编译时,编译器还不知道它的真实类型,所以这个对象看起来像A
.
// 非法 new B().me().doB();
所以,下面这个方法可以被调用。代码如下:
// 合法 new B().me().doA();
无论如何,我们可以将类型转换成B
,代码如下:
// 合法 ((B) new B().me()).doB();
如果添加一个C
类,代码如下:
/** * Coder: D瓜哥,http://www.diguage.com/ */ class C extends A { public void doBad() { System.out.println("Do C"); } }
然后,下面这行代码是合法的并且可以通过类型检查。代码如下:
// 合法 ((C) new B().me()).doBad();
编译器不知道它的真是类型,但是在运行时将会报错一个B
不能转换为C
的类型转换异常:
java.lang.ClassCastException: B cannot be cast to C
D瓜哥注:
在“简易Java(01):从HelloWorld中可以学到什么?”中,D瓜哥介绍过Java类加载的过程。方法调用关系会再类加载的链接阶段进行确定。在Java语言中符合“编译期可知,运行时不可变”的方法有静态方法和私有方法两大类,前者与类型直接关联,后者在外部不可被访问,这两种方法的各自特点决定了它们都不可通过继承或者别的方式重写其版本。因此他们都在类加载阶段就确定下来调用版本。
其他方法(除构造器外)则是在运行期根据实际类型确定方法执行版本的。这类方法的分派过程称为动态分派。关于“动态分派”更详细的描述,请看“参考资料”中的《深入理解Java虚拟机》的第八章第8.3.2节“分派”。
《Simple Java》翻译,《简易Java》走起!
参考资料
原文链接:https://wordpress.diguage.com/archives/81.html
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。
D瓜哥最近在研究什么呢?
研究怎么找工作,怎么找好工作!哈哈