让我们假设我们有三个(或更多)类
公共课A {}
公共B级扩展A {}
公共类C扩展B实现G {}
假设每个类都有自己的20个(或更多)方法.
铸造到C与铸造到A对性能有更大的影响吗? Java编译如何在幕后工作?
在向下投射时,是否必须通过反射检查所有方法和字段是否存在?
编辑:
类的大小(字段和方法的数量)是否会影响投射时的性能?
我对OpenJRE和Dalvik感兴趣.
作为参考,我知道可以毫无问题地完成向上转换.
最佳答案
转换的性能取决于JVM的实现.
JLS 5.5仅确定转换的要求(包括递归算法),但不对实现设置任何要求.实际上runtime cast rules in 5.5.3也是以同样的方式确定的.产生与提出的算法相同结果的所有JVM实现都被接受为适当的JVM.
通常,由于JVM必须检查对象的运行时类型,因此向下转换为C会花费更多时间.当转换为A时,它没有理由进行相同的检查,因为B扩展为A.
实际上,JVM并不关心方法和字段的数量.它只比较类型层次结构,你可以用反射检查它(o.getClass())
我做了如下示例代码,一个是downcast,另一个是upcast:
Object o = new Integer(1);
Integer i = (Integer) o;
Object o2 = i;
编译后的字节码如下:
0 new java.lang.Integer [16]
3 dup
4 iconst_1 <-- 1 as a parameter to the constructor
5 invokespecial java.lang.Integer(int) [18] <-- constructor
8 astore_1 [o] <-- store in 'o'
9 aload_1 [o]
10 checkcast java.lang.Integer [16] <-- DOWNCAST CHECK,SPECIAL BYTECODE
13 astore_2 [i]
14 aload_2 [i]
15 astore_3 [o2] <-- WITH UPCAST NO CHECK
因此,有一个特定的JVM指令,它使用给定的类检查堆栈顶部的元素.
有了向上,根本没有检查.
类的大小(字段数,方法,实际占用空间)无关紧要,因为转换会检查类(元数据,实际上是对象).
层次结构级别的数量以及实现的接口(如果转换为接口)的数量确实很重要,因为这是要检查的可遍历继承/实现树.
如果没有这种检查的某种缓存,我会感到惊讶.