Java反射嵌套匿名类

时间:2011-02-27 16:58:38

标签: java reflection

为什么这段代码会返回“class java.lang.Object”?

Object a = new Object() {
  public Object b = new Object(){
    public int c;
  };
};

System.out.println(a.getClass().getField("b").getType());

为什么内在类型会丢失?我怎样才能反映c字段?

编辑:

这个有效(正如在一些答案中指出的那样):

a.getClass().getField("b").get(a) ...

但是我必须调用一个getter,有没有办法只用反射元数据来反映c?

3 个答案:

答案 0 :(得分:5)

因为b被声明为Object

public Object b = ...;

变量类型(静态类型)与该变量引用的对象类型(运行时类型)之间存在区别。

Field.getType()返回该字段的静态类型。

如果要获取该字段引用的对象的运行时类型,则需要访问该对象并在其上调用getClass()(因为a被声明为Object因此b作为其成员不可见,您必须使用反射来访问它):

System.out.println(
     a.getClass().getField("b").get(a).getClass());

更新:如果不访问包含它的对象实例,则无法反映c。这就是为什么这些类型被称为匿名 - 包含c的类型没有名称,因此您不能将字段b声明为该类型的字段。

答案 1 :(得分:3)

让我们仔细看看这一行:

System.out.println(a.getClass().getField("b").getType());

首先,您获取a变量。它是Object的一些匿名子类。我们称之为MyClass$1。好的,到目前为止一切顺利。

接下来,调用getClass()方法。它返回a的类,即MyClass$1类的描述。但是,此描述与该类的任何特定实例无关。对于所有实例,该类都是相同的,无论是a还是其他任何实例(除非使用不同的类加载器)。但是,在这种特殊情况下,只能有一个实例,因为该类是匿名的,但机制仍然相同。

现在,从课程中获得字段b。由于该类与任何此类实例没有直接关联,因此该字段与a无关。它只是对类a的字段MyClass$1到底是什么的描述。

现在你得到它的类型。但由于它不依赖于任何实例,因此无法知道运行时类型。实际上,如果该类不是匿名的,那么您可以拥有许多MyClass$1个实例,每个实例在a中具有不同的值。或者你根本没有任何实例。所以getType()唯一能告诉你的是b的声明类型,它正是它所做的。那时b字段实际上可能是null,结果你仍会获得Object

Field类提供了get()方法来实际访问某个对象的特定字段,如下所示:

System.out.println(a.getClass().getField("b").get(a).getClass());

现在你得到像MyClass$1$1这样的东西,它是b字段引用的对象的匿名类的名称,a实例中的

答案 2 :(得分:1)

  

为什么内在类型会丢失?

因为您获取字段“b”(对象)的类型类型,而不是您将实例分配给“b”的匿名内部类的类型。

  

我如何反映c字段?

你可以用这个

System.out.println(a.getClass().getField("b").get(a).getClass().getField("c"));

代替。这将获得字段“b”及其类的值,但只有在保证“b”不为空时才有效。

这样做似乎表明设计不好,可能还有其他方法可以存档您想要做的事情。但是,如果不知道目的,这就是我能回答的一切。

相关问题