如何访问匿名对象内声明的字段?

时间:2013-05-10 20:00:56

标签: java visibility inner-classes anonymous-class

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

我收到此编译器错误:

$ 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

为什么?

6 个答案:

答案 0 :(得分:6)

  

为什么?

这是因为Object是变量o的静态类型,而Object没有属性x。以下原因完全无法编译:

public class X {
  public int x;

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

希望您的Java直觉在这个示例中是正确的,并且期望这个失败。所以,只需将这种直觉移植到你的榜样中。

  

如何访问匿名对象内声明的字段?

与我在示例中访问x的方式相同:反射。

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

如果我不能使用公共字段,为什么它会让我公开?

如果它不允许你创建公共领域,即使反思也不适合你,至少不像上面那样简单。

答案 1 :(得分:3)

你只能通过反思来做到这一点。该类没有名称,因此您必须将变量o声明为Object,而Object没有该成员。换句话说,不要这样做

答案 2 :(得分:1)

您可以通过反射访问该字段:

    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将命名该类并将其用作变量类型:

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

答案 3 :(得分:1)

您可以直接在匿名类创建表达式上访问它:

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

但是,你不能再使用创建的对象了,所以它有点无用。

答案 4 :(得分:0)

定义一个扩展Object的内部类(在您的特定情况下,您不应该写extends Object,无论如何。在您的课程中,定义您的字段,然后通过引用您的类型来访问它们

示例:

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

答案 5 :(得分:0)

在Java 10之后,您也可以使用'var'魔术(局部变量类型推断)

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