Pregunta

¿Hay alguna otra manera que no sea usar la reflexión para acceder a los miembros de una clase interna anónima?

¿Fue útil?

Solución

Las clases internas anónimas tienen un tipo pero no tienen nombre.

Puede acceder a campos no definidos por el supertipo nombrado. Sin embargo, una vez asignada a una variable de tipo con nombre, la interfaz se pierde.

Obviamente, puede acceder a los campos desde la propia clase interna. Una forma de agregar código es a través de un iniciador de instancia:

final AtomicInteger y = new AtomicInteger();
new Runnable() {
    int x;
    {
        x = 5;
        doRun(this);
        y.set(x);
    }
    public void run() {
        ... blah ...
    }
};

El valor devuelto por la expresión de clase interna anónima tiene el tipo anónimo, por lo que tiene una oportunidad de usarlo fuera de la clase misma:

final int y = new Runnable() {
    int x;
    {
        x = 5;
        doRun(this);
    }
    public void run() {
        ... blah ...
    }
}.x;

También puede pasarlo a través de un método declarado similar a:

<T extends Runnable> T doRun(T runnable);

Otros consejos

Puede usar clases locales en lugar de clases anónimas. Mira:

public class Test {
    public static void main(String... args) {
        class MyInner {
            private int value = 10;
        }

        MyInner inner = new MyInner();
        System.out.println(inner.value);
    }
}

Sin embargo, puede tener referencia de tipo MyInner solo en el cuerpo del método. Entonces, fuera del método, no podrá usar sus campos / métodos que no están declarados en su superclase ( java.lang.Object en este caso) o interfaz.


public class AccessAnonymous {
    private Runnable runnable; // to have instance of the class

    public static void main(String[] args) throws Exception {
        AccessAnonymous a = new AccessAnonymous();
        a.a(); // init field

        Class clazz = a.runnable.getClass();
        Field field = clazz.getDeclaredField("i");
        field.setAccessible(true);

        int int1 = field.getInt(a.runnable);
        System.out.println("int1=" + int1);
    }

    public void a() {
        runnable = new Runnable() {
            private int i = 1;

            public void run() {
                i = 90;
            }

        };
        runnable.run();// change value
    }
}

En el caso de las clases anónimas, también existe un compromiso entre el desorden causado por la clase y la conveniencia de tenerlo en el anonimato. Las clases complicadas rara vez pertenecen como anónimas, sino más bien como llamadas privadas internas.

En la mayoría de las clases anónimas, solo necesitamos '' alimentar '' conocimiento y puede hacerlo en la construcción. En algunas clases anónimas (por ejemplo, vehículos de valor de retorno) también nos importa un valor de retorno.

Como sabemos, no se debe acceder directamente a los miembros de datos, sino a un getter setter. Esto, si se encuentra en una situación en la que ha agregado muchos captadores y establecedores, probablemente esté haciendo algo mal de todos modos y no debería usar una clase anónima.

Si implementa una interfaz o extiende una clase existente, puede acceder a los miembros definidos en la interfaz o clase base.

Mr Fooz tiene razón, excepto que las interfaces solo pueden definir miembros constantes. la mejor manera sería agregar métodos getter / setter a su interfaz y luego usarlos para obtener su valor. pero luego para cada clase anónima tendrías que definir esos métodos (una especie de dolor).

Si desea un código legible y fácil de mantener, no use clases anónimas. Si usa clases anónimas y desea un código legible y mantenible, no use clases anónimas cuando necesite acceder al elemento en esa clase interna. Hay formas de hacerlo, pero te ruego que no uses ninguno de esos hacks. La legibilidad triunfa sobre todas las demás virtudes.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top