最终课程中的非最终方法

Aci*_*dic 31 java compiler-construction

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

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

提前致谢.

Ebo*_*ike 35

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

看这里:

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

和这里:

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

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

  • 请注意,在任何现代JVM中,唯一可以获得效率的地方是字段.JVM执行自己的分析以确定可以内联哪些方法,哪些局部变量只写入一次,等等. (3认同)
  • 要迂腐,这些方法是否隐含最终是没有实际意义的; 没有机会试图覆盖它们! (2认同)

Ste*_*n C 8

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

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

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

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

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

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

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

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


底线是:

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

  • 可能是一个性能优势,final在非方法final类,但是只有当你使用的是旧的Sun JVM,或用质量差的JIT编译器的一些其他Java/Java的类平台.

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


你在评论中写道:

@RussellZahniser我在许多地方的阅读方式不同.

互联网上充满了旧信息,其中大部分已经过时......或者从一开始就没有正确的信息.

  • 启发性的答案 - 最后我们不需要 final。最后,我们甚至不需要输入任何内容,因为编译器会弄清楚一切。 (2认同)

Bhe*_*ung 5

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

以下打印"false":

final class FinalClass {
    public void testMethod() {}
}

Method method = FinalClass.class.getDeclaredMethod("testMethod");
int m = method.getModifiers();
System.out.println(Modifier.isFinal(m));
Run Code Online (Sandbox Code Playgroud)