2010-11-12 8 views
53

Qué diferencia hace el final entre el código a continuación. ¿Hay alguna ventaja en declarar los argumentos como finales?Haciendo los argumentos del método java como final

public String changeTimezone(Timestamp stamp, Timezone fTz, Timezone toTz){ 
    return .... 
} 

public String changeTimezone(final Timestamp stamp, final Timezone fTz, 
     final Timezone toTz){ 
    return .... 
} 
+3

Hay analizadores de código que advierten si un parámetro se reutiliza o reasigna. (Lo mismo para las variables locales) En mi humilde opinión, esta es una mejor manera de detectar dichos parámetros si encuentra que cambiarlos no es deseable. –

+0

Posible duplicado de [¿Por qué debería usar la palabra clave "final" en un parámetro de método en Java?] (Https://stackoverflow.com/questions/500508/why-should-i-use-the-keyword-final-on -a-method-parameter-in-java) –

Respuesta

75

Como un parámetro de método formal es una variable local, puede acceder a ellos desde clases anónimas internas solo si se declaran como definitivas.

Esto le ahorra declarar otra variable último local en el cuerpo del método:

void m(final int param) { 
     new Thread(new Runnable() { 
      public void run() { 
       System.err.println(param); 
      } 
     }).start(); 
    } 
+18

+1: Este es un caso de uso importante, y el único momento en que * lo * necesita. (El resto del tiempo es solo una cuestión de lo que es conveniente para ayudar al programador.) –

+3

¿Puedo preguntar el razonamiento detrás de esto? – KodeWarrior

+11

No más necesario con Java 8. –

10

No hace mucha diferencia. Sólo significa que no se puede escribir:

stamp = null; 
fTz = new ...; 

pero todavía se puede escribir:

stamp.setXXX(...); 
fTz.setXXX(...); 

Es principalmente una pista para el programador de mantenimiento que se deduce que no se va a asignar una nuevo valor para el parámetro en algún lugar en el medio de su método donde no es obvio y, por lo tanto, puede causar confusión.

15

La final le impide asignar un nuevo valor a la variable, y esto puede ser útil para detectar errores tipográficos. Estilísticamente, es posible que desee mantener los parámetros recibidos sin cambios y asignar solo las variables locales, por lo que final ayudaría a aplicar ese estilo.

Debo admitir que rara vez recuerdo usar finales para los parámetros, tal vez debería.

public int example(final int basicRate){ 
    int discountRate; 

    discountRate = basicRate - 10; 
    // ... lots of code here 
    if (isGoldCustomer) { 
     basicRate--; // typo, we intended to say discountRate--, final catches this 
    } 
    // ... more code here 

    return discountRate; 
} 
0

Es solo una construcción en Java para ayudarle a definir un contrato y atenerse a él. Una discusión similar aquí: http://c2.com/cgi/wiki?JavaFinalConsideredEvil

BTW - (como dice el twiki), marcar args como final es generalmente redundante si se siguen buenos principios de programación y se ha hecho reasignar/redefinir la referencia del argumento entrante.

En el peor de los casos, si redefine la referencia args, no va a afectar el valor real pasado a la función, ya que solo se pasó una referencia.

2

La palabra clave final cuando se utiliza para los parámetros/variables en Java marca la referencia final. En caso de pasar un objeto a otro método, el sistema crea una copia de la variable de referencia y la pasa al método. Al marcar las nuevas referencias finales, las protege de la reasignación. Se considera a veces una buena práctica de codificación.

+1

Tengo que agregar algo: si los parámetros son primitivos, no veo diferencias. Además, si los parámetros son Colecciones (una lista de objetos ...), agregar final no puede evitar que se modifiquen. – Sam003

+1

La inmutabilidad es siempre un rasgo deseable. Java no lo tiene listo para usar. Hacer que las variables sean definitivas, al menos, garantiza la integridad de la referencia. – Sid

+0

Estoy de acuerdo. Pero si realmente queremos lograr la inmutabilidad de los objetos, podríamos tratar de hacer una copia profunda. – Sam003

19

Extracto de The final word on the final keyword

parámetros finales

El siguiente ejemplo declara parámetros finales:

public void doSomething(final int i, final int j) 
{ 
    // cannot change the value of i or j here... 
    // any change would be visible only inside the method... 
} 

última se utiliza aquí para asegurar que los dos índices i y j won ' t accidentalmente sea reiniciado por el método. Es una manera útil para proteger contra un error insidioso que erróneamente cambia el valor de sus parámetros.En general, los métodos abreviados son una mejor forma de proteger contra esta clase de errores , pero los parámetros finales pueden ser una adición útil a su estilo de codificación.

Tenga en cuenta que los parámetros finales no son considerada parte de la firma del método , y son ignorados por el compilador la hora de resolver las llamadas de método. Los parámetros pueden declararse finales (o no) sin influencia sobre cómo se reemplaza el método .

+8

Puede ser mejor usar objetos en lugar de primitivos para este ejemplo, ya que los cambios primitivos siempre serán visibles solo dentro del método. Y en el caso de los objetos, aún puedes cambiarlos. Simplemente no puedes señalar un nuevo objeto. De hecho, ahora que lo pienso, el final realmente no cambia nada en comparación con dejarlo fuera, salvo guardar una declaración de variable con AIC y hacer que el compilador señale modificaciones accidentales de parámetros que no quería modificar por algún motivo . –

1

Para el cuerpo de este método de la palabra clave final impedirá que las referencias argumento para ser reasignado accidentalmente dando un error de compilación en esos casos (la mayoría de los entornos de desarrollo se quejan de inmediato). Algunos pueden argumentar que usar final en general siempre que sea posible acelerará las cosas, pero ese no es el caso en las JVM recientes.

0

Estoy hablando de marcar variables y campos finales en general - no solo se aplica a los argumentos del método. (Los métodos de marcado/clases finales son una cosa completamente diferente).

Es un favor para los lectores/futuros mantenedores de su código. Junto con un nombre razonable de la variable, es útil y tranquilizador para el lector de su código ver/entender lo que representan las variables en cuestión, y es tranquilizador para el lector que cada vez que vea la variable en el mismo ámbito, el significado permanezca lo mismo, por lo que (s) no tiene que rascarse la cabeza para descubrir siempre qué significa una variable en cada contexto. Hemos visto demasiados abusos de "reutilización" de variables, que hace que incluso un pequeño fragmento de código sea difícil de entender.

-3

La palabra clave final le impide asignar un nuevo valor al parámetro. Me gustaría explicar esto con un ejemplo sencillo

Supongamos que tenemos un método

metodo1() {

Fecha fechaDeNacimiento = new Date ("1/1/2009");

method2 (dateOfBirth);

method3 (dateOfBirth); }

mehod2 pública (Fecha fechaDeNacimiento) {
.... ....

....
}

mehod2 pública (Fecha fechaDeNacimiento) {
....
.... ....

}

En el caso anterior si a "dateOfBirth" se le asigna un nuevo valor en method2, esto daría como resultado un resultado incorrecto del método3. Como el valor que se pasa al método3 no es lo que era antes de pasarse al método2. Entonces, para evitar esta palabra clave final se usa para los parámetros.

Y esta es también una de las mejores prácticas de codificación de Java.

+5

Eso no está del todo bien. Incluso si el argumento dateOfBirth cambia a otro valor en method2(), esto no tendría efecto en method2(), ya que Java pasa por valor y no por referencia. – Flo

Cuestiones relacionadas