最终课程中的非最终方法

我的问题很简单:
编译器是否将最终类中的所有方法视为最终自身? 将final关键字添加到final类中的方法是否有效?

我知道最后的方法有更好的内联机会,这就是我要问的原因。

提前致谢。

你是对的,最后一堂课中的所有方法都是隐含的最终方法。

看这里:

“请注意,您也可以声明一个完整的类final。声明为final的类不能被子类化。这在创建像String类这样的不可变类时尤其有用。”

和这里:

最终类中的所有方法都是隐式最终的。

您可能也对此感兴趣: Java final关键字的性能提示

编译器是否将最终类中的所有方法视为最终自身?

实际上,是的。 final类中的方法不能被覆盖。 向方法添加(或删除) final关键字对此规则没有任何影响。

将final关键字添加到final类中的方法是否有效?

在实践中,它的影响很小。 它对覆盖规则没有影响(见上文),对内联没有影响(见下文)。

可以在运行时告诉我是否使用final关键字声明了一个方法…使用reflection来查看方法的标志。 所以它确实有一定的效果,尽管它与99.99%的程序无关。

我知道最后的方法有更好的内联机会,这就是我要问的原因。

这种理解是不正确的 。 现代JVM中的JIT编译器会跟踪应用程序加载的类中未覆盖哪些方法。 它使用此信息和静态类型来确定特定调用是否需要虚拟类调度。 如果没有,则可以进行内联,并将根据方法体的大小来使用。 实际上,JIT编译器忽略final的存在/不存在,并使用更准确的方法来检测允许方法内联的方法调用。

(实际上它比这更复杂。应用程序可以动态加载导致JIT编译器的方法覆盖分析变得不正确的子类。如果发生这种情况,JVM需要使任何受影响的编译方法无效并导致它们被重新编译。)


底线是:

  • final类中添加final方法没有任何性能优势。

  • final类中的方法final 可能会有性能优势,但前提是您使用的是旧的Sun JVM,或者其他类似Java / Java的平台,而且质量较差的JIT编译器。

如果您关心性能,最好使用具有合适JIT编译器的最新/高性能Java平台,而不是使用可能导致您将来出现问题的final关键字污染您的代码库。


你在评论中写道:

@RussellZahniser我在很多地方都有不同的阅读方式。

互联网上充满了旧信息,其中大部分已经过时……或者从一开始就永远不正确。

可能是编译器将它们视为final。

以下打印“false”:

 final class FinalClass { public void testMethod() {} } Method method = FinalClass.class.getDeclaredMethod("testMethod"); int m = method.getModifiers(); System.out.println(Modifier.isFinal(m));