Diferencia entre final y efectivamente final

Resuelto alex asked hace 10 años • 15 respuestas

Estoy jugando con lambdas en Java 8 y encontré una advertencia local variables referenced from a lambda expression must be final or effectively final. Sé que cuando uso variables dentro de una clase anónima, deben ser finales en la clase externa, pero aún así, ¿cuál es la diferencia entre final y efectivamente final ?

alex avatar Jan 06 '14 02:01 alex
Aceptado

... a partir de Java SE 8, una clase local puede acceder a variables locales y parámetros del bloque adjunto que son finales o efectivamente finales. Una variable o parámetro cuyo valor nunca cambia después de su inicialización es efectivamente final.

Por ejemplo, supongamos que la variable numberLengthno se declara final y agrega la declaración de asignación marcada en el PhoneNumberconstructor:

public class OutterClass {  

  int numberLength; // <== not *final*

  class PhoneNumber {

    PhoneNumber(String phoneNumber) {
        numberLength = 7;   // <== assignment to numberLength
        String currentNumber = phoneNumber.replaceAll(
            regularExpression, "");
        if (currentNumber.length() == numberLength)
            formattedPhoneNumber = currentNumber;
        else
            formattedPhoneNumber = null;
     }

  ...

  }

...

}

Debido a esta declaración de asignación, la variable numberLength ya no es definitiva. Como resultado, el compilador de Java genera un mensaje de error similar a "las variables locales a las que se hace referencia desde una clase interna deben ser finales o efectivamente finales" donde la clase interna PhoneNumber intenta acceder a la variable numberLength:

http://codeinventions.blogspot.in/2014/07/difference-between-final-and.html

http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html

Suresh Atta avatar Jan 05 '2014 19:01 Suresh Atta

Creo que la forma más sencilla de explicar "efectivamente final" es imaginar agregar el finalmodificador a una declaración de variable. Si con este cambio el programa continúa comportándose de la misma manera, tanto en tiempo de compilación como en tiempo de ejecución, entonces esa variable es efectivamente final.

Maurice Naftalin avatar Jan 06 '2014 00:01 Maurice Naftalin

Esta variable a continuación es final , por lo que no podemos cambiar su valor una vez inicializada. Si lo intentamos obtendremos un error de compilación...

final int variable = 123;

Pero si creamos una variable como esta, podemos cambiar su valor...

int variable = 123;
variable = 456;

Pero en Java 8 , todas las variables son finales de forma predeterminada. Pero la existencia de la segunda línea en el código la hace no definitiva . Entonces, si eliminamos la segunda línea del código anterior, nuestra variable ahora es "efectivamente final" ...

int variable = 123;

Entonces... Cualquier variable que se asigne una vez y sólo una vez es "efectivamente final" .

Eurig Jones avatar Dec 23 '2016 17:12 Eurig Jones

Según los documentos :

Una variable o parámetro cuyo valor nunca cambia después de su inicialización es efectivamente final.

Básicamente, si el compilador encuentra que una variable no aparece en asignaciones fuera de su inicialización, entonces la variable se considera efectivamente final .

Por ejemplo, considere alguna clase:

public class Foo {

    public void baz(int bar) {
        // While the next line is commented, bar is effectively final
        // and while it is uncommented, the assignment means it is not
        // effectively final.

        // bar = 2;
    }
}
Mark Elliot avatar Jan 05 '2014 19:01 Mark Elliot