我的问题很简单:
编译器是否将最终类中的所有方法视为最终自身?将final
关键字添加到最终类中的方法是否有效?
我知道最后的方法更有可能被内联,这就是我要问的原因。
提前致谢。
答案 0 :(得分:33)
你是对的,最后一堂课中的所有方法都是隐含的最终方法。
“请注意,你也可以声明一个完整的类最终。一个类是 声明final不能被子类化。这对于特别有用 例如,在创建类似String类的不可变类时。“
最终类中的所有方法都是隐式最终的。
答案 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));