Доступ к внутренним анонимным членам класса - PullRequest
6 голосов
/ 26 ноября 2008

Есть ли другой способ, кроме как использовать отражение для доступа к членам анонимного внутреннего класса?

Ответы [ 7 ]

9 голосов
/ 26 ноября 2008

У анонимных внутренних классов есть тип, но нет имени.

Вы можете получить доступ к полям, не определенным именованным супертипом. Однако после присвоения именованной переменной типа интерфейс теряется.

Очевидно, вы можете получить доступ к полям внутри самого внутреннего класса. Один из способов добавления кода - через инициализатор экземпляра:

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

Значение, возвращаемое выражением анонимного внутреннего класса, имеет анонимный тип, поэтому у вас есть один шанс использовать его вне самого класса:

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

Вы также можете передать его через метод, объявленный как:

<T extends Runnable> T doRun(T runnable);
9 голосов
/ 26 ноября 2008

Вы можете использовать локальные классы вместо анонимного класса. Посмотрите:

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

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

Вы можете иметь ссылку типа MyInner только в теле метода. Поэтому вне метода вы не сможете использовать его поля / методы, которые не объявлены в его суперклассе (в данном случае java.lang.Object) или интерфейсе.

1 голос
/ 27 ноября 2008

В случае анонимных классов также существует компромисс между беспорядком, вызванным классом, и удобством его анонимности. Сложные классы редко принадлежат как анонимные, а именуются как private inner.

В большинстве анонимных классов нам нужно только «кормить» знания и делать это при строительстве. В нескольких анонимных классах (например, средства с возвращаемым значением) мы также заботимся об одном возвращаемом значении.

Как мы знаем, доступ к элементам данных должен осуществляться не напрямую, а с помощью метода получения. Это, если вы оказались в ситуации, когда вы добавили много методов получения и установки, вы, вероятно, все равно делаете что-то не так и не должны использовать анонимный класс.

1 голос
/ 26 ноября 2008

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
    }
}
0 голосов
/ 27 ноября 2008

Если вы хотите читаемый, обслуживаемый код, не используйте анонимные классы. Если вы используете анонимные классы и хотите читаемый, обслуживаемый код, не используйте анонимные классы, когда вам нужен доступ к элементу в этом внутреннем классе. Есть способы сделать это, но я прошу вас не использовать ни один из этих хаков. Читабельность превосходит все остальные достоинства.

0 голосов
/ 26 ноября 2008

Мистер Фуз прав, за исключением того, что интерфейсы могут определять только постоянные члены. лучший способ - добавить методы getter / setter в ваш интерфейс, а затем использовать их для получения вашей ценности. но тогда для каждого анонимного класса вы должны будете определить эти методы (что-то вроде боли).

0 голосов
/ 26 ноября 2008

Если он реализует интерфейс или расширяет существующий класс, вы можете получить доступ к членам, определенным в интерфейсе или базовом классе.

...