Доступ к внутренним анонимным членам класса
-
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 в ваш интерфейс, а затем использовать их для получения вашей ценности. но тогда для каждого анонимного класса вы должны будете определить эти методы (что-то вроде боли). Р>
Если вам нужен читабельный, обслуживаемый код, не используйте анонимные классы. Если вы используете анонимные классы и хотите читаемый, обслуживаемый код, не используйте анонимные классы, когда вам нужен доступ к элементу в этом внутреннем классе. Есть способы сделать это, но я прошу вас не использовать ни один из этих хаков. Читаемость превосходит все остальные достоинства.