JVM使用的虚拟表解析策略是什么意思? 有人可以详细解释一下吗?
答案 0 :(得分:5)
基本上任何未声明为final
的方法都可以在任何继承类中重写。虚拟表解析策略是Java如何动态地将方法调用分派给对象的运行时类型的方法定义。例如,如果您有一个对象s
被声明为Shape
类型但被实例化为new Circle()
(即Shape s = new Circle()
),那么您调用s.draw()
} ...如果Circle覆盖draw
,则需要调用Circle的draw方法版本,而不是Shape方法的版本。这些信息只能在运行时计算出来(如果传递一个Shape对象,它可以从编译器永远不会看到的JAR传入,因此编译器无法确定实例化Shape的哪个特定子类),因此,由VM调度方法调用到正确的方法定义(在这种情况下,由Circle提供的绘制版本)。
// Shape.java public class Shape { public void draw(){ System.out.println("I'm a Shape"); } } // Circle.java public class Circle extends Shape { public void draw(){ System.out.println("I'm a Circle"); } } // Elsewhere Shape s = new Circle(); s.draw(); // should print "I'm a Circle"
对于虚拟表的大多数实现,每个类都有一个表,其中每个条目是成员函数及其对应的地址。因此,圆形和形状的虚拟表在表格中都有一个用于“绘制”的条目,但圆形和形状的虚拟表每个都有绘制点的条目到它们各自对该函数的定义。然后,该类的每个实例都指向其给定类的虚拟表。因此,当您执行new Circle()
时,它包含指向Circle虚拟表的条目。当调用未声明为final
的方法时,通过在对象的虚拟表中查找适当的偏移量来调用适当的方法实现。