将private
和final
添加到同一方法是否多余?
class SomeClass {
//--snip--
private final void doStuff()
{
// private work here
}
}
如果是private
,那么任何人都无法覆盖它,对吗?
为什么可以添加final
关键字,如果它没有效果? (或者我错过了什么?)
答案 0 :(得分:51)
基本上,这是允许的,因为他们认为不值得设置禁止private
修饰符的特殊情况。这就像你如何将接口上的方法声明为public
,或者将接口中的嵌套类声明为static
,即使这些关键字隐含在接口中。您还可以在final
类等上声明final
方法。
当你添加冗余修饰符时,Java采取了不抱怨的立场。他们一贯地做到了。
答案 1 :(得分:5)
需要私有方法为final的一个边缘情况是使用SafeVarargs注释时。以下代码无法编译,因为私有方法不是最终的。
@SafeVarargs
private void method(List<String>... stringLists) {
//TODO a safe varargs operation
}
答案 2 :(得分:4)
它使语言更灵活,但语言不保证它会产生任何影响。使私有方法最终是对(JIT)编译器的提示。
Java语言规范notes:
可以将方法声明为final,以防止子类覆盖或隐藏它。
尝试覆盖或隐藏最终方法是编译时错误。
私有方法和在最终类(§8.1.1.2)中立即声明的所有方法都表现得像是最终的,因为无法覆盖它们。
在运行时,机器代码生成器或优化器可以&#34;内联&#34;最终方法的主体,用其主体中的代码替换方法的调用。内联过程必须保留方法调用的语义。特别是,如果实例方法调用的目标为null,则即使方法是内联的,也必须抛出NullPointerException。 Java编译器必须确保在正确的位置抛出异常,以便在方法调用之前以正确的顺序评估该方法的实际参数。
一个常见的误解是将一个类或方法声明为final 通过允许编译器直接插入来提高效率 方法调用的任何地方(参见内联扩展)。但是因为 方法在运行时加载,编译器无法执行此操作。只有 运行时环境和JIT编译器确切地知道哪些类具有 已经加载,因此只有他们能够做出何时决定 内联,无论方法是否是最终的
生成直接可执行的,特定于平台的机器代码的机器代码编译器是一个例外。使用静态时 链接时,编译器可以安全地假设方法和变量 编译时可计算的内容可以内联。