una que privada otra objeto nombre llevan internas interna interfaz estaticas dentro crear clases clase anonimas java java-8 inner-classes

que - Java dejó de cometer errores en variables no finales en clases internas(java 8)



que clases internas no llevan nombre (4)

Esta pregunta ya tiene una respuesta aquí:

Java 7 estaba diciendo "No se puede referir al mensaje de variable local no final definido en un ámbito adjunto" en el siguiente código:

public class Runner { public static void main(String[] args) { String message = "Hello world"; new Runnable() { @Override public void run() { System.out.println(message); } }.run(); } }

Java 8 no lo hace.

Sospecho que esto se trata de agregar características de programación funcional a Java.

¿Procesa el código de manera similar?


El message variable es efectivamente final . Citar de referencia de idioma

Si una variable es efectivamente final, agregar el modificador final a su declaración no introducirá ningún error en tiempo de compilación.

Por lo tanto, debido a message referencia del message no se cambia en ninguna parte dentro de su clase interna, el compilador la trata como efectivamente final.

Esto habría arrojado un error:

new Runnable() { @Override public void run() { message = "hey"; System.out.println(message); } }.run();

La razón por la cual el compilador java7 arroja un error es debido a un cambio de especificación para lambdas .

Cualquier variable local, parámetro formal o parámetro de excepción usado pero no. Cualquier variable local, parámetro formal o parámetro de excepción usado pero no declarado en una expresión lambda debe ser declarado final o ser efectivamente final (§4.12.4), o una compilación -se produce un error de tiempo donde se intenta el uso.

Clases internas anónimas y lambdas comparten las mismas reglas.


Java 8 (y Lambdas) introducen el término final efectivo : aunque no lo hayas eliminado con la palabra clave final , si no se modifica, es tan bueno como definitivo.

Cita del tutorial de Oracle: Clases locales :

Sin embargo, a partir de Java SE 8, una clase local puede acceder a las variables y parámetros locales del bloque envolvente que son finales o efectivamente finales . Una variable o parámetro cuyo valor nunca se cambia después de que se inicializa es efectivamente final.

Su mensaje es efectivamente final, por lo que es válido referirse a él desde clases internas anónimas y lambdas.

Si cambia el valor del mensaje, ya no será definitivo :

String message = "Hello world"; new Runnable() { @Override public void run() { System.out.println(message); } }.run(); message = "modified";

Y por lo tanto, recibe el siguiente error (de Eclipse):

El mensaje de variable local definido en un ámbito adjunto debe ser final o efectivamente final

O forma javac :

error: las variables locales a las que se hace referencia desde una clase interna deben ser finales o efectivamente finales


Java 8 hace implícitamente el message final porque nunca se modifica. Intenta modificarlo en cualquier lugar de tu código y obtendrás un error de compilación (porque esto elimina el final implícito).

Esto se llama efectivamente final . Cita de la documentación :

Sin embargo, a partir de Java SE 8, una clase local puede acceder a las variables y parámetros locales del bloque envolvente que son finales o efectivamente finales. Una variable o parámetro cuyo valor nunca se cambia después de que se inicializa es efectivamente final.


Sí, en cierto modo es.

Básicamente, se dieron cuenta de que el compilador ya tiene que decidir analizando el código cuando una variable local es "efectivamente final", es decir, su valor nunca se cambia.

Por lo tanto, la semántica no ha cambiado: si bien ya no es necesario declarar explícitamente la variable final , usted debe asegurarse de que nunca se reasigne.