Detener la reasignación de una variable
Si bien estas respuestas son intelectualmente interesantes, no he leído la respuesta simple y breve:
Use la palabra clave final cuando desee que el compilador evite que una variable se reasigne a un objeto diferente.
Si la variable es una variable estática, una variable miembro, una variable local o una variable de argumento / parámetro, el efecto es completamente el mismo.
Ejemplo
Veamos el efecto en acción.
Considere este método simple, donde las dos variables ( arg y x ) pueden ser reasignadas a diferentes objetos.
// 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.
}
Marque la variable local como final . Esto da como resultado un error del compilador.
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";
}
En su lugar, marquemos la variable del parámetro como final . Esto también resulta en un error del compilador.
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.
}
Moraleja de la historia:
Si desea asegurarse de que una variable siempre apunte al mismo objeto, marque la variable como final .
Nunca reasigne argumentos
Como buena práctica de programación (en cualquier lenguaje), nunca debe reasignar una variable de parámetro / argumento a un objeto que no sea el objeto pasado por el método de llamada. En los ejemplos anteriores, nunca se debe escribir la línea arg =. Como los humanos cometen errores y los programadores son humanos, solicitemos ayuda al compilador. Marque cada variable de parámetro / argumento como 'final' para que el compilador pueda encontrar y marcar tales reasignaciones.
En retrospectiva
Como se señaló en otras respuestas ... Dado el objetivo de diseño original de Java de ayudar a los programadores a evitar errores tontos, como leer más allá del final de una matriz, Java debería haber sido diseñado para aplicar automáticamente todas las variables de parámetro / argumento como 'final'. En otras palabras, los argumentos no deben ser variables . Pero la retrospectiva es una visión 20/20, y los diseñadores de Java tenían las manos ocupadas en ese momento.
Entonces, ¿siempre agregar finala todos los argumentos?
¿Debemos agregar finala todos y cada uno de los parámetros del método que se declara?
- En teoría sí.
- En la práctica, no.
➥ Agregue finalsolo cuando el código del método es largo o complicado, donde el argumento puede confundirse con una variable local o miembro y posiblemente reasignarse.
Si acepta la práctica de no reasignar nunca un argumento, estará inclinado a agregar un finala cada uno. Pero esto es tedioso y hace que la declaración sea un poco más difícil de leer.
Para el código simple corto donde el argumento es obviamente un argumento, y no una variable local ni una variable miembro, no me molesto en agregar el final. Si el código es bastante obvio, sin posibilidad de que yo ni ningún otro programador realice tareas de mantenimiento o refactorice accidentalmente confundiendo la variable de argumento como algo más que un argumento, entonces no se moleste. En mi propio trabajo, agrego finalsolo código más largo o más involucrado donde un argumento puede confundirse con una variable local o miembro.
Otro caso agregado para la integridad
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
}