4

Java 允许您在匿名类中声明新字段,但我不知道如何从外部访问它们,即使将它们设置为 public 也不允许我这样做。

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

为什么?

4

6 回答 6

8

为什么?

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

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

如果它不让你公开领域,即使反射也不适合你,至少不像上面那样简单。

于 2013-05-10T20:38:18.870 回答
3

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

于 2013-05-10T20:05:51.613 回答
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));

如果要访问字段,更好的样式是命名类并将其用作变量类型:

    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);
于 2013-05-10T20:44:48.313 回答
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);
   }
}

但是,您不能再使用创建的对象,所以它有点没用。

于 2013-05-10T23:47:24.157 回答
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");
     }
}
于 2014-03-04T16:35:11.703 回答
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);
   }
}
于 2020-12-13T12:53:15.710 回答