Question

Existe-t-il un autre moyen que d'utiliser la réflexion pour accéder aux membres d'une classe interne anonyme?

Était-ce utile?

La solution

Les classes internes anonymes ont un type mais pas de nom.

Vous pouvez accéder aux champs non définis par le supertype nommé. Cependant, une fois assignée à une variable de type nommée, l'interface est perdue.

Évidemment, vous pouvez accéder aux champs depuis la classe interne elle-même. Une façon d’ajouter du code consiste à initialiser une instance:

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

La valeur renvoyée par l'expression de classe interne anonyme a le type anonyme, vous avez donc une chance de l'utiliser en dehors de la classe elle-même:

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

Vous pouvez également le transmettre via une méthode déclarée similaire à:

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

Autres conseils

Vous pouvez utiliser des classes locales à la place de la classe anonyme. Regarde:

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

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

Vous pouvez cependant avoir une référence de type MyInner uniquement dans le corps de la méthode. Donc en dehors de la méthode, vous ne pourrez pas utiliser ses champs / méthodes qui ne sont pas déclarés dans sa super classe ( java.lang.Object dans ce cas) ou interface.


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
    }
}

Dans le cas des classes anonymes, il existe également un compromis entre le fouillis causé par la classe et la commodité de l’avoir anonyme. Les classes compliquées appartiennent rarement à un groupe anonyme mais à un groupe nommé privé interne.

Dans la plupart des classes anonymes, il suffit de " alimenter " connaissances et peut le faire à la construction. Dans quelques classes anonymes (véhicules de retour, par exemple), nous nous soucions également d’une valeur de retour.

Comme nous le savons, les membres de données ne doivent pas être directement accessibles, mais plutôt à l'aide d'un getter-setter. Ceci, si vous vous retrouvez dans une situation où vous avez ajouté beaucoup de getters et de setters, vous faites probablement quelque chose de mal de toute façon et vous ne devriez pas utiliser une classe anonyme.

S'il implémente une interface ou étend une classe existante, vous pouvez accéder aux membres définis dans l'interface ou la classe de base.

M. Fooz a raison, sauf que les interfaces ne peuvent définir que des membres constants. Le meilleur moyen serait d'ajouter des méthodes getter / setter à votre interface, puis de les utiliser pour obtenir votre valeur. mais ensuite, pour chaque classe anonyme, vous devrez définir ces méthodes (une sorte de douleur).

Si vous voulez du code lisible et maintenable, n'utilisez pas de classes anonymes. Si vous utilisez des classes anonymes et souhaitez un code lisible et maintenable, n'utilisez pas de classes anonymes lorsque vous devez accéder à l'élément de cette classe interne. Il existe des moyens de le faire, mais je vous prie de ne pas utiliser ces hacks. La lisibilité prime sur toutes les autres vertus.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top