在 Java 中,子类化和覆盖相同的方法是否会导致运行时效率低下



我不久前在某处读到过 - 我不记得在哪里,子类化几次并且每次覆盖相同的方法,都会导致运行时效率低下。

例如:

Class A{protected myFunction(){}}
Class B extends A{@Override myFunction(){}}
Class C extends B{@Override myFunction(){}}

从 A 类内部调用myFunction()现在"慢"是真的吗?我记得作者描述了由于指针查找而导致的低效率,必须这样做才能访问正确的覆盖方法。

更详细地解释一下:

在每个加载类的 JVM 私有表示中,都有一个方法指针表。 编译类 X 时,方法 xMethod1、xMethod2、xMethod3 在表中分配插槽 -- 始终以相同的顺序分配。 假设 Object 有插槽 0-10,所以 X 有插槽 11、12 和 13。

当您将类 Y 定义为 X 的子类时,将从 X 的方法表中复制其方法表的 Y 插槽 0-13 的私有表示形式。 然后,在新表中为 yMethod1、yMethod2、yMethod3 分配插槽 14、15 和 16。 因此,可以通过索引调用方法并始终获得正确的版本。

现在,如果类 Y 还定义了它自己的 xMethod2 版本,则指向该版本的指针将放置在槽 12 处 Y 类的表示形式的方法表中,覆盖类 X 的方法指针。

创建对象实例时,

指向类的私有表示形式的指针放置在实例标头中,因此,当调用方法时,可以查阅方法表并访问正确的方法(方法表索引值已有效地编译到字节码中)。

所以调用函数是:从对象头获取私有表示指针,在私有表示中获取表指针,使用文字索引的索引表,获取方法指针,将控制权转移到方法。

接口方法

:接口的调用机制可能有几种不同的实现,但我怀疑大多数都遵循我们所做的,而不是索引用于虚拟调用的"方法表",而是查询哈希表。 不是使用方法名称进行搜索,而是使用预先计算的方法标识符来搜索哈希表并获取方法指针,因此该机制快速而紧凑。

同样,该机制并不"关心"事物被子类化/子接口的深度。

相关内容

最新更新