Arrêter la réaffectation d'une variable
Bien que ces réponses soient intellectuellement intéressantes, je n'ai pas lu la réponse simple et courte:
Utilisez le mot-clé final lorsque vous souhaitez que le compilateur empêche qu'une variable soit réaffectée à un autre objet.
Que la variable soit une variable statique, une variable membre, une variable locale ou une variable argument / paramètre, l'effet est entièrement le même.
Exemple
Voyons l'effet en action.
Considérez cette méthode simple, où les deux variables ( arg et x ) peuvent toutes deux être réaffectées à des objets différents.
// Example use of this method:
// this.doSomething( "tiger" );
void doSomething( String arg ) {
String x = arg; // Both variables now point to the same String object.
x = "elephant"; // This variable now points to a different String object.
arg = "giraffe"; // Ditto. Now neither variable points to the original passed String.
}
Marquez la variable locale comme finale . Il en résulte une erreur de compilation.
void doSomething( String arg ) {
final String x = arg; // Mark variable as 'final'.
x = "elephant"; // Compiler error: The final local variable x cannot be assigned.
arg = "giraffe";
}
Au lieu de cela, marquons la variable de paramètre comme finale . Cela entraîne également une erreur de compilation.
void doSomething( final String arg ) { // Mark argument as 'final'.
String x = arg;
x = "elephant";
arg = "giraffe"; // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
}
Morale de l'histoire:
Si vous voulez vous assurer qu'une variable pointe toujours vers le même objet, marquez la variable finale .
Ne jamais réaffecter d'arguments
Comme bonne pratique de programmation (dans n'importe quel langage), vous ne devez jamais réaffecter une variable de paramètre / argument à un objet autre que l'objet passé par la méthode appelante. Dans les exemples ci-dessus, il ne faut jamais écrire la ligne arg =
. Puisque les humains font des erreurs et que les programmeurs sont humains, demandons au compilateur de nous aider. Marquez chaque variable de paramètre / argument comme «finale» afin que le compilateur puisse trouver et marquer de telles réaffectations.
En rétrospective
Comme indiqué dans d'autres réponses… Étant donné l'objectif de conception original de Java d'aider les programmeurs à éviter les erreurs stupides telles que la lecture après la fin d'un tableau, Java aurait dû être conçu pour appliquer automatiquement toutes les variables de paramètre / argument comme «finales». En d'autres termes, les arguments ne doivent pas être des variables . Mais le recul est une vision de 20/20, et les concepteurs Java avaient les mains pleines à l'époque.
Alors, toujours ajouter final
à tous les arguments?
Devrions-nous ajouter final
à chaque paramètre de méthode déclaré?
- En théorie, oui.
- En pratique, non.
➥ Ajouter final
uniquement lorsque le code de la méthode est long ou compliqué, où l'argument peut être confondu avec une variable locale ou membre et éventuellement réaffecté.
Si vous achetez dans la pratique de ne jamais réattribuer un argument, vous serez enclin à ajouter un final
à chacun. Mais cela est fastidieux et rend la déclaration un peu plus difficile à lire.
Pour un code simple court où l'argument est évidemment un argument, et non une variable locale ni une variable membre, je ne me donne pas la peine d'ajouter le final
. Si le code est assez évident, sans aucune chance pour moi ni pour aucun autre programmeur de faire de la maintenance ou de refactoriser par erreur la variable argument comme autre chose qu'un argument, alors ne vous embêtez pas. Dans mon propre travail, j'ajoute final
uniquement du code plus long ou plus impliqué où un argument peut être confondu avec une variable locale ou membre.
Un autre cas ajouté pour l'exhaustivité
public class MyClass {
private int x;
//getters and setters
}
void doSomething( final MyClass arg ) { // Mark argument as 'final'.
arg = new MyClass(); // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
arg.setX(20); // allowed
// We can re-assign properties of argument which is marked as final
}