2008-11-25 84 views
57

在Java中,您可以使用final关键字限定局部变量和方法参数。为什么在Java中将局部变量和方法参数标记为“final”?

public static void foo(final int x) { 
    final String qwerty = "bar"; 
} 

这样做会导致无法在方法主体中重新分配x和qwerty。

这种做法将您的代码推向通常被认为是加号的不变性方向。但是,它也往往会在各处出现“最终”的代码。对Java中局部变量和方法参数的最终关键字有什么看法?

+2

请参阅http://stackoverflow.com/questions/266806/is-there-any-performance-reason-to-declare-method-parameters-final-in-java#266981和http://stackoverflow.com/ questions/137868/using-final-modifier-whenever-applicable-in-java and http://stackoverflow.com/questions/154314/when-to-use-final – Robin 2008-11-25 14:36:21

回答

53

你应该尽量做到这一点,只要它是适当的。除了用于在您“意外”尝试修改值时发出警告,它还会向编译器提供信息,以便更好地优化类文件。这是Robert Simmons,Jr所着的书“Hardcore Java”中的一个要点。实际上,本书的第二章全面介绍了使用final来促进优化并防止逻辑错误。静态分析工具,如PMD和Eclipse的内置SA标记这些种情况出于这个原因。

27

我个人认为,这是浪费时间。我相信视觉混乱和增加冗长是不值得的。

我从来没有遇到过我已经重新分配(记住,这不会使对象不可变,所有这些都意味着您不能重新分配变量的另一个引用)错误的变量。

但是,当然,这全是个人喜好;-)

+5

+1因为我认为它不仅仅是方法身体和逻辑错误(我从来没有跑过,因为非最终变量,FWIW),但也关于可读的方法签名。我无法看到声明为final的参数如何使签名更具可读性。简单类型通过值传递,所以不可修改。复杂类型是按引用传递的,但引用是按值传递的,因此不可修改。最后只是签名的读者的噪音。 – Matthias 2010-07-18 11:17:04

0

为什么你想要?您编写了该方法,因此修改该方法的任何人都可以始终从qwerty中删除最终的关键字并重新分配它。至于方法签名,同样的推理,尽管我不确定它会对你的类的子类做些什么......他们可能会继承最后一个参数,即使他们重写了方法,也无法去定义x。试试看看它是否可行。

那么,唯一真正的好处是如果你使参数不可变并且它传递给了孩子。否则,你只是混乱你的代码没有特别好的理由。如果它不会强迫任何人遵守你的规则,那么你最好留下一个好评,因为你为什么不应该改变该参数或变量,而不是给出最终修饰符。

编辑

在回应评论,我会补充一点,如果你看到的性能问题,让你的局部变量和参数可以最终让编译器来优化你的代码更好。但是,从您的代码不可变性的角度来看,我支持我的原始声明。

+0

如果JRE或编译器知道该对象已完成,则可以执行更多优化。 – paxdiablo 2008-11-25 04:25:46

+0

当然,但这不是问题。在使你的代码不可变的方面,它并不真正起作用。但是,您的判断非常正确,因为它可能比不使用它稍快,并且在性能成为问题时应予以考虑。 – Elie 2008-11-25 04:27:30

+0

正如我在Pax的回答中所评论的那样,我相当肯定,通过局部变量的最终结果,没有改进性能,因为JVM可以为你猜出。 – SCdF 2008-11-25 04:31:00

5

由于Java的“pass by reference”行为(偶尔)混淆本质,我绝对同意最终确定参数var's。

完成本地var的似乎有点矫枉过正IMO。

6

在局部变量的情况下,我倾向于避免这种情况。它会导致视觉混乱,而且通常是不必要的 - 一个函数应该足够短或集中在一个单一的影响,让你很快看到你正在修改不应该的东西。

在幻数的情况下,我会把它们作为一个常量私人字段,而不是在代码中。

我只在需要的情况下使用final(例如,将值传递给匿名类)。

0

我让Eclipse在匿名类中使用它,因为我使用Google Collection API而增加了这个类。

0

如果我们认为它们不会被重新分配或不应被重新分配,我们在这里为局部变量做这件事。

参数不是最终的,因为我们有一个Checkstyle-Check检查重新分配参数。当然,没有人会想要重新分配参数变量。

2

最终有三个很好的理由:

  • 实例变量的构造函数只设置成为不可改变
  • 方法不能被重写成为决赛中,真正的原因使用,默认情况下不
  • 局部变量或要在方法内部的不一致类中使用的参数需要是最终的

与方法类似,本地变量和参数不需要声明为final。就像其他人之前所说的那样,这会使代码变得越来越不可读,编译器性能优化的代价变得越来越小,这对大多数代码片段来说并不是真正的原因。

3

是的。

这是关于可读性。当你知道变量只被赋值一次而且只赋值一次时,更容易推断程序的可能状态。

一个体面的替代方法是在分配参数时或者多次分配变量(除了循环变量之外)时打开IDE警告。

8

使参数最终保证该方法中任何位置使用的值指传递的值。否则,你不得不精神分析给定位置上的所有代码,以知道该参数在那个点上有什么值。

因此,使用最终使你的代码的可读性和可维护,全部由自己:)

最后的局部变量取决于意图,是在我的观点不那么重要了。取决于发生的情况。

2

虽然它造成了一点点混乱,但值得推荐final。 Ides例如eclipse可以自动将final设置为如此。

2

制作局部变量和方法参数final是非常重要的,如果你想将这些参数传递给匿名类 - 就像你实例化一个匿名线程并且想要访问run()方法体内的那些参数。

除此之外,我不确定通过编译器优化可以获得更好的性能。它是由具体的编译器实现是否要优化它...

这将是很好的知道使用final任何性能统计...

相关问题