How to access fields declared inside anonymous obj

2019-07-14 16:09发布

问题:

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?

回答1:

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.



回答2:

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.



回答3:

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


回答4:

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.



回答5:

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