views:

863

answers:

7

Is there any way other than using reflection to access the members of a anonymous inner class?

A: 

If it implements an interface or extends an existing class, you can access the members defined in the interface or base class.

Mr Fooz
A: 

Mr Fooz is right, except that interfaces can only define constant members. the best way would be to add getter/setter methods to your interface and then use those to get your value. but then for each anonymous class you would have to define those methods (kind of a pain).

luke
Method are members of their types just as fields are.
erickson
+5  A: 

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.

Ivan Dubrov
Wow... never seen those before. Bizarre. Can't say I like it a lot, but it's interesting nonetheless :)
Jon Skeet
They are called local classes.
Tom Hawtin - tackline
If I'm not wrong, the class that you have shown is just another class with limited visibility.. right? I meant the question to know possible access to members of an anonymous class object.
sarav
+1  A: 

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
    }
}
geeeeeeeeeek
+3  A: 

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);
Tom Hawtin - tackline
A: 

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.

sdellysse
+1  A: 

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.

Uri