Voir @TravisG pour une explication des règles de scoping impliquées. La seule raison pour laquelle vous utiliseriez une variable de boucle finale comme celle-ci est que vous auriez besoin de la fermer dans une classe interne anonyme.
import java.util.Arrays;
import java.util.List;
public class FinalLoop {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(new Integer[] { 0,1,2,3,4 });
Runnable[] runs = new Runnable[list.size()];
for (final int i : list) {
runs[i] = new Runnable() {
public void run() {
System.out.printf("Printing number %d\n", i);
}
};
}
for (Runnable run : runs) {
run.run();
}
}
}
La variable de la boucle n'est pas dans la portée du Runnable lorsqu'il est exécuté, mais seulement lorsqu'il est instancié. Sans la variable final
mot-clé, la variable de la boucle ne serait pas visible par le Runnable lorsqu'il sera finalement exécuté. Même si elle l'était, ce serait la même valeur pour tous les Runnables.
Il y a environ 10 ans, vous auriez pu constater une très légère amélioration de la vitesse en utilisant final sur une variable locale (dans de rares occasions) ; ce n'est plus le cas depuis longtemps. Maintenant, la seule raison d'utiliser final est de vous permettre d'utiliser une fermeture lexicale comme celle-ci.
En réponse à @mafutrct :
Lorsque vous écrivez du code, vous le faites pour deux publics. Le premier est l'ordinateur qui, tant que la syntaxe est correcte, sera satisfait des choix que vous faites. Le second est destiné à un futur lecteur (souvent vous-même). Dans ce cas, l'objectif est de communiquer l'"intention" du code, sans en masquer la "fonction". Les caractéristiques du langage doivent être utilisées de manière idiomatique, avec le moins d'interprétations possible, afin de réduire les ambiguïtés.
Dans le cas de la variable de la boucle, l'utilisation de final pourrait être utilisée pour communiquer l'une des deux choses suivantes : affectation unique ou fermeture. Une analyse triviale de la boucle vous dira si la variable de boucle est réassignée ; cependant, en raison de l'entrelacement de deux chemins d'exécution lors de la création d'une fermeture, il peut être facile de ne pas voir que la fermeture avait l'intention de capturer la variable. À moins, bien sûr, que vous n'utilisiez final pour indiquer l'intention de capturer, auquel cas il devient évident pour le lecteur que c'est ce qui se passe.