最终课程中的非最终方法

时间:2012-01-07 01:08:13

标签: java compiler-construction

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

我知道最后的方法更有可能被内联,这就是我要问的原因。

提前致谢。

3 个答案:

答案 0 :(得分:33)

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

See here:

  

“请注意,你也可以声明一个完整的类最终。一个类是   声明final不能被子类化。这对于特别有用   例如,在创建类似String类的不可变类时。“

And here:

  

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

您可能也对此感兴趣:Performance tips for the Java final keyword

答案 1 :(得分:8)

  

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

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

  

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

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

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

  

我知道最后的方法更有可能被内联,这就是我要问的原因。

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

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


底线是:

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

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

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


您在评论中写道:

  

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

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

答案 2 :(得分:5)

可能是编译器将它们视为最终版。

以下打印“false”:

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

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