una que otra objeto nombre llevan internas interna interfaz interfaces estaticas ejemplos dentro crear clases clase anonimas java constructor inner-classes

java - que - Extraña sintaxis para crear instancias de una clase interna



que clases internas no llevan nombre (6)

No me imaginaba que encontraría una sintaxis radicalmente nueva en Java en esta etapa, pero he aquí, acabo de encontrar algo:

El contexto exacto y lo que el código siguiente debería hacer es bastante irrelevante: está ahí solo para dar algún tipo de contexto.

Intento crear sintéticamente un evento en IT Mill Toolkit, así que escribí este tipo de línea:

buttonClick(new Button.ClickEvent(button));

Pero, Eclipse me da el siguiente mensaje de error:

No se puede acceder a ninguna instancia adjunta de tipo Button. Debe calificar la asignación con una instancia adjunta de tipo Button (por ejemplo, xnew A () donde x es una instancia de Button).

Cuando reescribo la línea anterior de la siguiente manera, ya no se queja:

buttonClick(button.new ClickEvent(button)); // button instanceof Button

Entonces, mi pregunta es: ¿qué significa exactamente la última sintaxis y por qué no funciona el primer fragmento? ¿De qué se queja Java y qué está haciendo en la segunda versión?

Información de fondo: tanto Button como Button.ClickEvent son clases públicas no abstractas.


Button.ClickEvent es una clase interna no estática, por lo que una instancia de esta clase solo puede existir encerrada en una instancia de Button.

En su segundo ejemplo de código tiene una instancia de Button y crea una instancia de ClickEvent en esta instancia de Button ...


Las clases internas (como Button.ClickEvent ) necesitan una referencia a una instancia de la clase externa ( Button ).

Esa sintaxis crea una nueva instancia de Button.ClickEvent con su referencia de clase externa establecida en el valor del button .

Aquí hay un ejemplo: ignore la falta de encapsulado, etc., solo para fines de demostración:

class Outer { String name; class Inner { void sayHi() { System.out.println("Outer name = " + name); } } } public class Test { public static void main(String[] args) { Outer outer = new Outer(); outer.name = "Fred"; Outer.Inner inner = outer.new Inner(); inner.sayHi(); } }

Consulte la sección 8.1.3 de la especificación para obtener más información sobre las clases internas y las instancias adjuntas.


Para evitar confundirse a usted y a otros programadores con esta característica que rara vez se usa, siempre puede hacer que las clases internas estén estáticas.

En caso de que se necesite una referencia a la clase externa, puede pasarla explícitamente en el constructor.


Tu código se compilaría si hubieras escrito

buttonClick(new Button().ClickEvent(button));

en lugar de

buttonClick(new Button.ClickEvent(button));

como constructor es un método y cuando llamas a un método en Java debes pasar la lista de argumentos, incluso cuando está vacía.


Una clase interna no estática en Java contiene una referencia oculta que apunta a una instancia de la clase externa en la que está declarada. Por lo tanto, el mensaje de error que recibió originalmente le dice que no puede crear una nueva instancia de la clase interna sin especificar también una instancia de la clase externa para que se adjunte.

Quizás la razón por la que no ha visto esa sintaxis es que las clases internas a menudo se asignan en un método de la clase externa, donde el compilador se encarga de esto automáticamente.


De hecho, puedes hacer eso , pero debes declarar que ClickEvent static dentro de Button , y entonces no deberías tener ningún problema al usar tu sintax:

buttonClick(new Button.ClickEvent(button));

Básicamente static hace que la clase ClickEvent pertenezca directamente al Button clase en lugar de una instancia específica (es decir, un new Button() ) de Button .

Siguiendo al ejemplo de @Jon Skeet:

// Button.java class Button { public static class ClickEvent { public ClickEvent(Button b) { System.out.println("Instance: " + this.toString()); } } } // Test.java public class Test { public static void main(String[] args) { Button button = new Button(); buttonClick(new Button.ClickEvent(button)); } public static void buttonClick (Button.ClickEvent ce) { } }