最终变量解释



我知道编译器如何解释Java中的final关键字,但我们程序员应该如何解释它的含义?应该是:

1) 此变量不能更改(例如由内部类使用)

2) 我不打算更改此变量(可能对成员变量有一些优化好处)。

我之所以这么问,是因为我编写过默认情况下所有内容都声明为final的代码(上面的选项2),在我看来,这会使关键字贬值,并隐藏真正无法更改的值!将变量声明为final是否仍有性能优势?

默认情况下,所有最终结果都是好的。你越能根据不变性对代码进行建模,就越容易推理。

在我看来,使用final与性能无关。它是关于对代码的其余部分进行断言(没有任何东西会改变这个变量),这可以帮助读者理解代码,并且可以由编译器进行检查。

编辑:以上是我对领域的看法。对于局部变量(包括参数),我个人只在匿名内部类中使用final。这与字段不同,因为:

  • 很容易看到该方法的整个上下文,如果不是,那本身就是一个问题
  • 由于它不代表对象(或类)的状态,因此不变性的好处并不真正适用

应放弃final关键字,它应在所有适用的情况下都是标准的,并且最终性只能使用等关键字来撤销

this_variable_will_change_unexpectedly_behind_your_back

任何IDE都不应该自动完成这个关键字,也不应该使用Ctrl-V插入它。

我不久前写了一篇关于这方面的文章。

阅读代码的最终帮助:

  • 如果不使用final,一切都可能是可变的(潜在的混乱)
  • 它强制在使用变量之前设置变量(在构造函数中很有用)

通过使用final,你可以告诉编译器一些关于你的代码的信息,它会反过来帮助你。

第二个选项是一种保护措施。它会阻止您意外地更改或重新分配。因此,提供它是很有用的,当您决定要更改该变量时,可以删除它。

我不能对Jon已经说过的内容添加太多内容,但为了完整性,JLS 17.5.3表示最终字段也可能导致优化;

如果在字段声明中将最终字段初始化为编译时常量表达式(§15.28),则可能不会观察到对最终字段的更改,因为在编译时使用常量表达式的值替换该最终字段

我不明白你为什么认为缺少价值。

当我看到所有的最终变量时,这意味着类是不可变的。这是一件好事,因为不可变类本质上是线程安全的。

最终变量通常是一件好事。请注意,这只是意味着变量不能被重新分配,但它指向的对象可以更改,如果它是可变的。

性能方面,final允许更积极的编译器优化:

该规范允许对最终字段进行积极的优化。在线程中,允许使用未在构造函数中发生的对最终字段的修改来重新排序最终字段的读取。

将每个变量声明为final并不会使final关键字贬值。它有助于开发人员在调试应用程序时排除修改变量的可能性,尤其是在应用程序的多线程环境中。

随着java 8的发布,我们又有了一个概念,称为"effectively final variable"

从lambda表达式引用的局部变量必须是最终变量或有效的最终变量

如果变量在本地块中初始化后未进行修改,则该变量被视为最终有效。这意味着您现在可以在匿名类或lambda表达式中使用不带final关键字的局部变量,前提是它们必须是有效的final。

如果您不想将有效的final声明为final变量,那么在使用lambda表达式/匿名类时,此新功能会对您有所帮助。您可以避免为effective final变量声明final关键字。看看这篇文章

确实使用了final变量,这样就没有人可以更改值,它在java中是常量。

让我举个例子

我已经创建了一个包,其他人也可以使用它,现在需要设置一些配置变量才能正确运行它。比如说它的登录包。因此,像这样的加密选项可能很少

encryption_method=HASH_encryption

encryption_method=SYMMETRIC_encryption

我们可以定义最终变量,而不是传递整数1、2、3,这有助于开发人员以更可读的形式使用它。当然,我不希望用户更改它,所以我将其保留为最终变量,否则内部逻辑可能会破坏