我发现一些 Java IDE 有这样一条规则,即在不询问用户的情况下将事情定为最终版本。例如,只需打开一个缺少任何“final”关键字的文件,IDE 就会在各处插入一堆关键字,尤其是在变量上。
我的论点一直是:“如果 IDE 可以在算法上做到这一点,那么 JVM 也可以”
这个论点站得住脚吗?Java 开发人员什么时候应该使用“final”关键字?每个可能是 final 的变量都应该这样声明吗?
谢谢!
我的论点一直是:“如果 IDE 可以在算法上做到这一点,那么 JVM 也可以”
这个论点站得住脚吗?
没有。因为当 IDE 执行此操作时(我没有看到任何默认情况下不询问就执行此操作,即使您可以显式配置它以这样做)开发人员可以检查这是否真的是他们想要的决定。这可以防止其他代码违背开发者的意愿做事。
如果只在执行时完成,那将破坏整个目的。如果我创建一个字段final
以防止其他代码修改它,如果其他代码尝试修改它,我想要一个编译时错误。如果它只是留给 JVM,我不能依赖不修改它的代码。
Java 开发人员什么时候应该使用“final”关键字?
对于字段,当字段打算在构造函数中初始化并且此后不再更改时。
对于类,当您尚未将类设计为子类 (IMO) 时。
对于方法,当您没有为子类设计代码来覆盖该方法时。
对于局部变量,您希望在其中访问匿名内部类中的变量。(当然,您也可以将它们用于其他局部变量 - 我不倾向于,但我知道有些人这样做。当然,在方法之外的代码中看不到这种差异。)
你太模糊了,final 意味着很多东西: http://en.wikipedia.org/wiki/Final_(Java)
另外,请参阅此相关讨论:https://softwareengineering.stackexchange.com/questions/115690/why-declare-final-variables-inside-methods链接到以下文章:
http://www.javapractices.com/topic/TopicAction.do?Id=23
自由地使用 final 关键字来传达您的意图。final 关键字具有多个含义:
- 最终类不能扩展
- 最终方法不能被覆盖
- final 字段、参数和局部变量一旦设置就不能改变它们的值
在最后一种情况下,原语的“值”是通常意义上的理解,而对象的“值”是指对象的身份,而不是它的状态。一旦设置了最终对象引用的标识,它仍然可以更改其状态,但不能更改其标识。将原始字段声明为 final 会自动确保该字段的线程安全。
有些人习惯性地将参数声明为 final,因为这几乎总是所需的行为。其他人认为这很冗长,而且没有什么真正的好处。
始终将 final 与局部变量一起使用(适当时)也很有用。它引起了对非最终局部变量的注意,这些局部变量通常具有更多与之相关的逻辑(例如,结果变量、累加器、循环变量)。许多人觉得这很冗长。一种合理的方法是仅当方法中至少有一个非最终局部变量时才对局部变量使用 final ;这有助于快速将非最终局部变量与其他局部变量区分开来。
使用最终:
- 清楚地传达您的意图
- 允许编译器和虚拟机执行较小的优化
- 清楚地标记行为更简单的项目 - final 说,“如果你正在寻找复杂性,你不会在这里找到它。”
只有当局部变量是 . 时,它才能在内部类中使用final
。
final
修饰符可用于保护自己免受 setter 方法中的失误。
public void setLimit(int limit) {
/*this.*/limit = limit;
}
显然是错误的;放入this.
是需要的。使用final
如
public void setLimit(final int limit) {
limit = limit;
}
把它变成一个编译错误。
每个可能是 final 的变量都应该这样声明吗?
是的。
很多人没有意识到编译器可以做多少来帮助您避免常见问题:
// Final parameters cannot be reassigned. This sometimes happens accidentally
// and sometimes because people see them as convenient local variables.
publc void myFunction(final int myIntParam) {
// Let's declare a local variable
final String myLocalString;
// ... there's some code here ...
// Here, the compiler knows whether this variable has been assigned
// The programmer knows that it has been assigned only once
return myLocalString.toUpperCase(Locale.ENGLISH);
}