Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中,子类化和重写同一方法是否会导致运行时效率低下?_Java - Fatal编程技术网

在Java中,子类化和重写同一方法是否会导致运行时效率低下?

在Java中,子类化和重写同一方法是否会导致运行时效率低下?,java,Java,我不久前在某个地方读到过,我不记得在哪里,多次子类化,每次都重写同一个方法,导致运行时效率低下 例如: Class A{protected myFunction(){}} Class B extends A{@Override myFunction(){}} Class C extends B{@Override myFunction(){}} 从类A中调用myFunction()现在是否“更慢”?我记得作者描述了由于指针查找而导致的效率低下,为了访问正确的覆盖方法,必须进行指针查找。更详

我不久前在某个地方读到过,我不记得在哪里,多次子类化,每次都重写同一个方法,导致运行时效率低下

例如:

Class A{protected myFunction(){}}

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

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

从类A中调用
myFunction()
现在是否“更慢”?我记得作者描述了由于指针查找而导致的效率低下,为了访问正确的覆盖方法,必须进行指针查找。

更详细地解释一下:

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

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

现在,如果类Y也定义了它自己的xMethod2版本,那么指向该版本的指针将放在插槽12处Y类表示的方法表中,覆盖类X的方法指针

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

因此,调用函数是:从对象头获取私有表示指针,在私有表示中获取表指针,使用文本索引索引表,获取方法指针,将控制转移到方法

接口方法:接口调用机制可能有几种不同的实现方式,但我怀疑大多数实现方式都与我们的实现方式相同,它们不是索引用于虚拟调用的“方法表”,而是参考哈希表。与使用方法名称进行搜索不同,使用预先计算的方法标识符来搜索哈希表并获取方法指针,因此该机制既快速又紧凑


同样,该机制并不“关心”事物的子类/子接口有多深。

如果你有一堆子类(同一个分支),但只有最顶层的父级实现了该方法,我会认为它会更“低效”。后期绑定必须遍历整个层次结构才能找到实现。在你的例子中,它只需要查看实例的类型就可以找到一个实现。什么版本的Java?谁告诉你的都是。一旦类被加载,JVM甚至看不到超类方法。事实上,调用第27个子类中的方法与调用第27超类中的方法没有任何性能差异——一旦类被加载,它们都是相同的。(在接口上调用方法的效率较低,但无论接口方法位于层次结构中的何处,成本都是相同的。)。。。在热点重新编译的这些日子里,接口开销也可能消失。