很多书都说java最终实例方法(不是私有)使用静态绑定,而其他实例方法(非私有)使用动态绑定。但是在编译时,它们都使用" invokevirtual" JVM指令。当JVM执行" invokevirtual"时,可以区分最终方法和非最终方法。说明?我原本认为最终方法使用" invokespecial"作为私有实例方法,因为它们都使用静态绑定。
答案 0 :(得分:2)
编译后的表格是JLS §13.4.17在第13章“二进制兼容性”中的直接结果:
13.4.17。
final
方法将声明为
final
的方法更改为不再声明为final
不会破坏与现有二进制文件的兼容性。
这意味着调用方的形式不应反映目标方法在编译时是否为final
(或当存在不同表示形式时,不允许在运行时产生实际差异)
要与其他形式的调用进行比较,无法在不破坏与调用者兼容性的情况下删除static
修饰符,因此,使用专用的invokestatic
指令对调用形式进行编码是一致的
对于private
方法的调用,调用者必须在同一类中,因此,在添加或删除private
修饰符时(仅考虑有效的调用者),将对其进行重新编译,因此使用没有问题。在同一类中调用invokespecial
方法时的private
。从JDK 11开始,private
方法可能会被属于同一嵌套组的其他类中的调用者调用;在这种情况下,其他类中的这些调用者将不使用invokespecial
。
因此final
和非final
方法之间的区别确实在运行时发生,当JVM知道实际的目标方法 if 时,这种区别就发生了。符合条件的JVM必须拒绝试图覆盖final
方法的类,但是它们不需要对调用进行优化。实际上,当今的JVM能够优化所有未被覆盖的方法的调用,而不管此属性是否已由final
修饰符强制执行。唯一的不同是,将新类加载到JVM中会覆盖非final
方法,这可能会导致调用方的优化。
答案 1 :(得分:0)
没有其他字节码指令可以调用由invokevirtual
以外的类声明的实例方法。它的名字令人困惑。它也可以命名为invokeClassMethod
或invokeclass
。实际上编译器不会特别处理最终方法。 invokespecial
用于调用构造函数和静态初始值设定项。