Доступ к внутренним анонимным членам класса

StackOverflow https://stackoverflow.com/questions/319765

  •  11-07-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

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

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

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);

Другие советы

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

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 ) или в интерфейсе.


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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top