Is there any way other than using reflection to access the members of a anonymous inner class?
Anonymous inner classes have a type but no name.
You can access fields not defined by the named supertype. However once assigned to a named type variable, the interface is lost.
Obviously, you can access the fields from within the inner class itself. One way of adding code is through an instance initialiser:
final AtomicInteger y = new AtomicInteger();
new Runnable() {
int x;
{
x = 5;
doRun(this);
y.set(x);
}
public void run() {
... blah ...
}
};
The value returned by the anonymous inner class expression has the anonymous type, so you have one chance to use it outside of the class itself:
final int y = new Runnable() {
int x;
{
x = 5;
doRun(this);
}
public void run() {
... blah ...
}
}.x;
You can also pass it through a method declared similar to:
<T extends Runnable> T doRun(T runnable);
You can use local classes instead anonymous class. Look:
public class Test {
public static void main(String... args) {
class MyInner {
private int value = 10;
}
MyInner inner = new MyInner();
System.out.println(inner.value);
}
}
You can have reference of MyInner
type only in the method body though. So outside of the method you will not be able to use its fields/methods that are not declared in its super class (java.lang.Object
in this case) or interface.
In the case of anonymous classes, there is also a tradeoff between the clutter caused by the class and the convenience of having it anonymous. Complicated classes rarely belong as anonymous but rather as named private inner.
In most anonymous classes, we only need to "feed" knowledge and can do it at construction. In a few anonymous classes (e.g., return value vehicles) we also care about one return value.
As we know, data members should not directly be accessed but rather with a getter setter. This, if you find yourself in a situation that you have added lots of getters and setters, you are probably doing something wrong anyway and shouldn't be using an anonymous class.
If it implements an interface or extends an existing class, you can access the members defined in the interface or base class.
If you want readable, maintainable code, don't use anonymous classes. If you use anonymous classes and want readable, maintainable code, don't use anonymous classes when you need to access the element in that inner class. There are ways of doing so, but I beg of you to not use any of those hacks. Readability trumps all other virtues.
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
}
}