为什么这段代码会返回“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?
答案 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”不为空时才有效。
这样做似乎表明设计不好,可能还有其他方法可以存档您想要做的事情。但是,如果不知道目的,这就是我能回答的一切。