考虑一个超类引用变量持有子类对象的引用,并且该特定子类重写其超类方法之一。现在,如果我们调用重写方法,将调用子类实现。在Java中,这涉及到RTTI ..?
class A { void Show(){ System.out.println("This is A"); } }
class B extends A{
void show(){
System.out.println("This is B");
}
}
答案 0 :(得分:4)
是的,它确实涉及运行时类型识别。 Java VM根据对象的类型查找调用的适当方法。
然而,当大多数人提到“运行时类型信息”时,他们谈论的是C ++。
如果您在询问Java VM是否使用C ++ RTTI,答案是否定的。
答案 1 :(得分:4)
不,它没有。 RTTI(运行时类型信息)是一个C ++术语,指的是在运行时保留类型信息,因此与Java中的反射更相关。您所询问的只是面向对象语言的通常动态调度。动态调度(根据运行时类型确定调度方法调用的位置,即动态信息)是面向对象编程的一个不可或缺的概念,而反射是语言不是真正需要面向对象的。
答案 2 :(得分:3)
您的示例说明了方法调用的简单多态或动态调度。在C ++术语中,您需要将此方法声明为“虚拟”,因此称为虚方法调用/调度。在Java中,不需要特殊的语法,并且它可能发生在任何实例方法调用中。
这是否等于“RTTI”是一个有争议的问题。 (首先,它取决于术语的含义!)当然,需要一些信息才能进行调度,但(理论上)这些信息不足以允许运行时识别类型。在Java案例中,该信息的详细信息以及它的表示方式是特定于JVM的。
还有一些重点:
Java字节码编译器发出的字节码有三个不同的字节码,用于调用实例方法。当需要进行虚方法调度时,使用“invokeinterface”和“invokevirtual”字节码,当不需要时,使用“invokespecial”字节码。
JIT编译器进一步优化本机代码,以避免在不需要的情况下进行虚拟方法调度。
即使编译器设法取消虚拟方法调度的开销,每个对象也需要一些在运行时识别其实际类(类型)的方法,以支持instanceof
运算符, -casting,Object.getClass()
方法以及依赖于它们的各种事物。因此,从这个角度来看,某种RTTI始终存在。
答案 3 :(得分:1)
我认为它被称为“虚拟查找”,如果这就是RTTI的意思,它会对运行时产生影响。
答案 4 :(得分:0)
对于类(而不是接口)上的Java方法调用,JVM不需要担心它是什么特定的类。从A派生的类中的所有show
方法都在特定类的方法表的元素26(以选择数字)中。所以JVM只需要从对象头获取类指针,索引到方法表到第26个条目(这是一个运行时常量)并调用该方法。
接口更复杂,必须使用更接近哈希表查找的方法来查找方法。