在增强型for循环中使用final循环变量的目的是什么?

26

我理解下面这个语句的工作原理。

for(final Animal animal : animalList){
//do some function
}

但是在这里使用final关键字的目的是什么?


4
这只是意味着变量 animal 不能被重新赋值,比如 animal = new Animal(); //在循环代码内部 - Luiggi Mendoza
@Luiggi -> 在每次迭代中,变量animal不会被分配一个新的引用吗? - Learn More
请注意注释:循环内部代码 - Luiggi Mendoza
2
@LearnMore 每次循环都会重新声明整个变量。 - Chris Bode
感谢您的回复。Tala和Kan的答案更加明确了这一点。 - Learn More
即使您不将“Animal animal”标记为“final”并在“for”循环内重新分配它,存储在“Collection”中的值也不会被修改,因为它只是一个副本。以此为基础,StephenC正确地说:“这可能只是一种避免意外更改循环变量的方法”,并提供了其他答案都没有考虑到的另一个原因。 - Luiggi Mendoza
5个回答

36

这样做有两个可能的原因:

  • 这可能只是一种避免在循环体中意外更改循环变量的方法。(或者用于记录循环变量不会被更改的事实。)

  • 这可能是为了可以在匿名内部类中引用循环变量。例如:

for(final Animal animal : animalList){
    executor.submit(new Runnable(){
        public void run() {
            animal.feed();
        }
    });
}

如果在此示例中省略了final,将会导致编译错误。

更新:在Java 8及更高版本中,这不再是编译错误。非局部变量现在只需要是有效的final。简单来说,这意味着该变量在初始声明/初始化后没有被赋值(使用赋值运算符或前/后增量或减量运算符)。


10

添加final关键字在这里不会产生性能差异,只是需要确保它在循环中不被重新赋值。

为避免可能导致混淆的情况,请这样做。

 for(Animal animal : animalList){
       //do some function
       animal = anotherAnimal;
       // use animal variable here
    }
您可能还需要在循环内使用此变量的匿名函数。

3

这意味着一旦for循环设置了animal的值,它的值就不能再改变。如果你在循环中的某个时候需要在匿名类中引用animal,那么可能需要这样做。

即使没有明确要求,将不会改变的变量定义为final也是一个好习惯。它可以帮助你捕捉错误,并使代码更加自我说明。


2

1
我并不认为这是Java的最佳实践。如果你认为或知道它是,请添加一个证明链接。 - Luiggi Mendoza
2
@LuiggiMendoza 只要有机会将某些东西标记为 final,我就会选择这样做。如果我错了,请纠正我 :) - Suresh Atta
1
你认为在setter方法中声明参数为final是最佳实践吗?此外,你提供的链接并没有真正说明将变量标记为final和不标记之间的区别。请注意,在两个示例中都可以使用continue关键字,行为将是相同的。 - Luiggi Mendoza
1
@LuiggiMendoza 是的,我相信这个说法。无论你在哪里有机会 - Suresh Atta
2
这是“一个好主意”,但不是“最佳实践”。只有当大多数从业者(即大多数经验丰富的Java开发人员)都同意它是最佳解决方案时,才能称之为最佳实践。在我看来,大多数Java开发人员不会同意你应该“随时”声明循环变量为final。 - Stephen C
显示剩余3条评论

0

这段代码是等价于下面这段代码的语法糖:

for (final Iterator<Animal> iterator = animals.iterator(); iterator.hasNext(); ) {
  final Animal animal = iterator.next();

}

我认为它回答了这个问题。


7
我不理解一个Animal怎么能轻易地变成String。不,这并没有回答问题。 - Luiggi Mendoza
@LuiggiMendoza 抱歉,那是个打字错误。如果他知道什么是final变量,那么理解起来就很容易了。顺便说一下,在C#中这是不可能做到的。 - kan
我认为发布的问答中的答案更加合适。 - Luiggi Mendoza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接