在 Java 中,您可以使用 final 关键字限定局部变量和方法参数。
public static void foo(final int x) {
final String qwerty = "bar";
}
这样做会导致无法在方法主体中重新分配 x 和 qwerty。
这种做法将您的代码推向不变性的方向,这通常被认为是一个优点。但是,它也倾向于使代码混乱,到处都出现“final”。您对 Java 中局部变量和方法参数的 final 关键字有何看法?
您应该在适当的时候尝试这样做。除了在您“意外”尝试修改值时发出警告之外,它还向编译器提供信息,可以更好地优化类文件。这是 Robert Simmons, Jr 所著的《Hardcore Java》一书中的要点之一。事实上,本书第二章的全部内容都在使用 final 来促进优化和防止逻辑错误。出于这个原因,诸如 PMD 和 Eclipse 的内置 SA 等静态分析工具标记了这些情况。
我个人的看法是,这是浪费时间。我相信视觉上的混乱和增加的冗长是不值得的。
我从来没有遇到过重新分配错误的情况(请记住,这不会使对象不可变,这意味着您不能重新分配对变量的另一个引用)错误的变量。
但是,当然,这都是个人喜好;-)
使参数最终保证在方法中的任何位置使用的值都引用传递的值。否则,您必须在心理上解析给定位置上方的所有代码,以了解该参数在该点的值。
因此,不使用 final 会使您的代码本身的可读性和可维护性降低:)
最终的局部变量取决于意图,在我看来并不那么重要。取决于发生了什么。
对于局部变量,我倾向于避免这种情况。它会导致视觉混乱,并且通常是不必要的 - 函数应该足够短或专注于单个影响,以便让您快速看到您正在修改不应该修改的内容。
在幻数的情况下,无论如何我会将它们作为一个常量私有字段而不是在代码中。
我只在必要的情况下使用final(例如,将值传递给匿名类)。
由于 Java 的“按引用传递”行为的(偶尔)令人困惑的性质,我绝对同意最终化参数 var。
最终确定本地 var 似乎有点矫枉过正 IMO。
是的,请动手。
这是关于可读性。当您知道变量被分配一次且仅一次时,就更容易推断程序的可能状态。
一个不错的替代方法是在分配参数时打开 IDE 警告,或者在多次分配变量(循环变量除外)时打开 IDE 警告。
final 有三个很好的理由:
与方法一样,局部变量和参数也不需要声明为 final。正如其他人之前所说,这会使代码变得不那么可读,编译器性能优化几乎没有,这并不是大多数代码片段的真正原因。
尽管它会造成一些混乱,但值得将final
. final
如果你配置它,IDEs 例如 eclipse 可以自动放置。
final
如果您想将这些参数传递给匿名类,则制作局部变量和方法参数是必不可少的——就像您实例化一个匿名线程并希望在 run() 方法的主体中访问这些参数一样。
除此之外,我不确定通过编译器优化获得更好的性能是否会带来性能优势。是否要优化它取决于特定的编译器实现......
很高兴知道使用final
...的任何性能统计信息
你为什么想要?您编写了该方法,因此任何修改它的人都可以始终从 qwerty 中删除 final 关键字并重新分配它。至于方法签名,同样的推理,虽然我不确定它会对你的类的子类做什么......它们可能会继承最终参数,即使它们覆盖了方法,也无法取消最终化 x。试一试,看看它是否有效。
那么,唯一真正的好处是,如果您将参数设置为不可变并将其传递给子级。否则,您只是无缘无故地弄乱您的代码。如果它不会强迫任何人遵循您的规则,那么您最好留下一个好的评论,说明您为什么不应该更改该参数或变量而不是给出最终修饰符。
编辑
作为对评论的回应,我将补充说,如果您发现性能问题,将局部变量和参数设置为 final 可以让编译器更好地优化您的代码。但是,从代码不变性的角度来看,我坚持我原来的说法。
我让 Eclipse 在匿名类中使用它们时为我做这件事,由于我使用了 Google Collection API,这种情况正在增加。
如果我们认为它们不会被重新分配或不应该被重新分配,我们会在这里为局部变量执行此操作。
参数不是最终的,因为我们有一个 Checkstyle-Check 来检查重新分配参数。当然,没有人愿意重新分配参数变量。