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 final
a todos los argumentos?
¿Debemos agregar final
a todos y cada uno de los parámetros del método que se declara?
- En teoría sí.
- En la práctica, no.
➥ Agregue final
solo 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 final
a 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 final
solo 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
}