method inner classes anonyme java inner-classes

inner - protected class java



¿Por qué las clases internas de Java requieren variables de instancia externas "finales"? (5)

final JTextField jtfContent = new JTextField(); btnOK.addActionListener(new java.awt.event.ActionListener(){ public void actionPerformed(java.awt.event.ActionEvent event){ jtfContent.setText("I am OK"); } } );

Si omito el final , veo el error " No se puede hacer referencia a una variable no final jtfContent dentro de una clase interna definida en un método diferente ".

¿Por qué una clase interna anónima necesita que la variable de instancia de las clases externas sea definitiva para acceder a ella?


Los métodos en una clase anónima realmente no tienen acceso a variables locales y parámetros de método. Por el contrario, cuando se crea una instancia de un objeto de la clase anónima, las copias de las variables locales finales y los parámetros del método a los que se refieren los métodos del objeto se almacenan como variables de instancia en el objeto. Los métodos en el objeto de la clase anónima realmente acceden a las variables de instancia ocultas. [1]

Por lo tanto, las variables locales y los parámetros de método accedidos por los métodos de la clase local deben declararse finales para evitar que sus valores cambien después de la instancia del objeto.

[1] http://www.developer.com/java/other/article.php/3300881/The-Essence-of-OOP-using-Java-Anonymous-Classes.htm


Bueno, primero, relájese, y por favor baje esa arma.

DE ACUERDO. Ahora, la razón por la que el lenguaje insiste en eso es que hace trampa para proporcionar acceso a las funciones de clase interna a las variables locales que anhelan. El tiempo de ejecución hace una copia del contexto de ejecución local (y etc., según corresponda), y por lo tanto insiste en que haga que todo sea final para que pueda mantener la honestidad.

Si no lo hizo, entonces el código que cambió el valor de una variable local después de que se construyó su objeto pero antes de que se ejecute la función de clase interna puede ser confuso y extraño.

Esta es la esencia de gran parte del alboroto en torno a Java y los "cierres".

Nota: el párrafo de apertura fue una broma en referencia a algunos textos de mayúsculas en la composición original del PO.



La razón es que Java no admite totalmente los denominados "cierres", en cuyo caso la final no sería necesaria, sino que ha encontrado un truco al permitir que el compilador genere algunas variables ocultas que se utilizan para dar la funcionalidad que se ve.

Si desensambla el código de bytes generado, puede ver cómo lo hace el compilador, incluidas las variables ocultas con nombres extraños que contienen copias de las variables finales.

Es una solución elegante para ofrecer funcionalidad sin tener que inclinar el idioma hacia atrás para hacerlo.

Editar: Para Java 8, las lambdas ofrecen una forma más concisa de hacer lo que se hacía anteriormente con las clases anónimas. Las restricciones en las variables también se han desvinculado de "final" a "esencialmente final"; no es necesario que lo declare final, pero si se trata como si fuera final (podría agregar la palabra clave final y su código aún se compilaría) puede ser usado. Este es un cambio realmente agradable.


Las variables en torno a la definición de la clase viven en la pila, por lo que probablemente desaparezcan cuando se ejecute el código dentro de la clase interna (si desea saber por qué, busque la pila y el montón). Es por eso que las clases internas en realidad no usan las variables en el método contenedor, pero están construidas con copias de ellas.

Esto significa que si cambia la variable en el método que lo contiene después de construir la clase interna, su valor no cambiará en la clase interna, aunque lo esperaría. Para evitar confusiones allí, Java requiere que sean definitivas, por lo que espera no poder modificarlas.