Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access fields declared inside anonymous object without reflection?

It's possible to make anonymous classes have new fields in Java:

class A {
   public static void main(String[] args) {
       Object o = new Object() {
           public int x = 0;
           {
               System.out.println("x: " + x++);
               System.out.println("x: " + x++);
           }
       };
       System.out.println(o.x);
   }
}

But they can't be accessed in this example, because o is of type Object:

$ javac A.java && java A
A.java:10: cannot find symbol
symbol  : variable x
location: class java.lang.Object
       System.out.println(o.x);
                           ^
1 error

Note that o is actually not an Object, it's an instance of a different class extending Object. This class has one public field x. Does this class have a name? How can I make o be the proper type so I can get access to o.x? (Note that it's possible to do this with reflection, but I want to do it statically).

like image 237
Dog Avatar asked Mar 25 '23 00:03

Dog


2 Answers

This class does have a name. It's A$1. However, you can't access this at compile time (the compiler creates A$1 for you). Thus, you can't access the field without reflection.

If you're in Eclipse, you can use Source menu (AltShiftS) → Convert Anonymous Class to Nested to convert it to a "real" class automatically.

Alternatively, you could have:

class A {
   public static void main(String[] args) {
       I o = new I() {
           public int x = 0;
           {
               System.out.println("x: " + x++);
               System.out.println("x: " + x++);
           }
           public int getX() { return x; }
       };
       System.out.println(o.getX());
   }
   interface I {
       public int getX();
   }
}

EDIT: Here's a really evil way to accomplish this that you should not do:

class A {
   public static void main(String[] args) {
       Object o = new Object() {
           public int x = 0;
           {
               System.out.println("x: " + x++);
               System.out.println("x: " + x++);
           }

           public Object clone() {
               // BAD BAD BAD
               return x;
           }
       };
       try {
           System.out.println(o.clone());
       } catch (CloneNotSupportedException cnse) {
           assert false;
       }
   }
}
like image 180
wchargin Avatar answered Apr 06 '23 04:04

wchargin


You could access it directly on the anonymous class creation expression:

class A {
   public static void main(String[] args) {
       System.out.println(new Object() {
           public int x = 0;
           {
               System.out.println("x: " + x++);
               System.out.println("x: " + x++);
           }
       }.x);
   }
}

But then, you can't otherwise use the object created anymore, so it's kinda useless.

like image 22
newacct Avatar answered Apr 06 '23 02:04

newacct