Question

Java lets you declare new fields inside anonymous classes, but I can't figure out how to access them from outside, even setting them to public doesn't let me.

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

I get this compiler error:

$ 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

Why?

Was it helpful?

Solution

Why?

It's because Object is the static type of the variable o, and Object doesn't have the property x. The following fails to compile for the exact same reason:

public class X {
  public int x;

  public static void main(String[] args) {
    Object o = new X();
    o.x = 3;
  }
}

Hopefully, your Java intuition is right on this example and you expect this to fail. So just transplant that intuition to your example.

How to access fields declared inside anonymous object?

Same way as you'd access x in my example: reflection.

Object o = new X();
o.getClass().getField("x").setInt(o, 3);

Why does it let me make public fields if I can't use them?

If it didn't let you make public fields, even reflection wouldn't work for you, at least not as simply as above.

OTHER TIPS

You could only do that by reflection. The class has no name, so you had to declare the variable o as an Object, and Object does not have that member. In other words, don't do this.

You could acces the field by reflection:

    Object o = new Object() {
       public int x = 0;
       {
           System.out.println("x: " + x++);
           System.out.println("x: " + x++);
       }
   };
   System.out.println(o.getClass().getField("x").get(o));

Better Style would be to name the class and use it as variable type, if you want to access field:

    class MyObject {
       public int x = 0;
       {
           System.out.println("x: " + x++);
           System.out.println("x: " + x++);
       }
   }
   MyObject o = new MyObject();
   System.out.println(o.x);

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.

Define an internal class that extends Object (in your specific case you should not write extends Object as it is done anyway. In your class, define your fields and than access them by reference of your type.

Example:

void func() {
     class MyInt extends Integer {
         boolean isSane = true;
     }
     MyInt intInstance = new MyInt();
     if (intInstance .isSane) {
         System.out.println("sane integer");
     }
}

also after Java 10 you can use 'var' magic (Local Variable Type-Inference)

class A {
   public static void main(String[] args) {
       // Object o = new Object() {
       var o = new Object() {
           public int x = 0;
           {
               System.out.println("x: " + x++);
               System.out.println("x: " + x++);
           }
       };
       System.out.println(o.x);
   }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top