Java 反映嵌套匿名类
为什么这段代码返回“class java.lang.Object”?
Object a = new Object() {
public Object b = new Object(){
public int c;
};
};
System.out.println(a.getClass().getField("b").getType());
为什么inner-inner类型会丢失?如何反映 c 字段?
编辑:
这个有效(正如一些答案中指出的那样):
a.getClass().getField("b").get(a) ...
但是我必须调用 getter,有没有什么方法可以仅使用反射元数据来反射 c ?
Why does this code return "class java.lang.Object" ?
Object a = new Object() {
public Object b = new Object(){
public int c;
};
};
System.out.println(a.getClass().getField("b").getType());
Why does the inner-inner type get lost? How can I reflect the c field ?
Edit:
This one works (as pointed out in some answers):
a.getClass().getField("b").get(a) ...
But then I have to invoke a getter, is there any way to reflect c with only reflection meta data?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
因为
b
被声明为Object
:变量类型(静态类型)和该变量引用的对象类型(运行时类型)之间存在区别。
Field.getType()
返回字段的静态类型。如果您想获取字段引用的对象的运行时类型,您需要访问该对象并对其调用
getClass()
(因为a
被声明为对象
,因此b
作为其成员不可见,您必须使用反射来访问它):更新:您无法反射
c
而不访问包含它的对象的实例。这就是这些类型被称为匿名的原因 - 包含c
的类型没有名称,因此您无法将字段b
声明为该类型的字段。Because
b
is declared asObject
:There is a distinction between type of variable (static type) and type of the object referenced by that variable (runtime type).
Field.getType()
returns static type of the field.If you want to get runtime type of the object referenced by the field, you need to access that object and call
getClass()
on it (sincea
is declared asObject
and thereforeb
is not visible as its member you have to use reflection to access it):UPDATE: You can't reflect
c
without accessing the instance of object containing it. That's why these types are called anonymous - a type containingc
has no name, so that you can't declare fieldb
as a field of that type.让我们仔细看看这一行:
首先,获取
a
变量。它是 Object 的某个匿名子类。我们将该类命名为MyClass$1
。好的,到目前为止一切顺利。接下来,调用 getClass() 方法。它返回a的类,即
MyClass$1
类的描述。不过,此描述与该类的任何特定实例无关。所有实例的类都是相同的,无论是a
还是其他任何东西(除非使用不同的类加载器)。然而,在这种特殊情况下,只能有一个实例,因为该类是匿名的,但机制仍然相同。现在,您可以从类中获取字段
b
。由于该类不直接绑定到任何此类实例,因此该字段也与a
无关。它只是对类MyClass$1
的字段a
到底是什么的描述。现在你得到了它的类型。但由于它不绑定到任何实例,因此它无法知道运行时类型。事实上,如果该类不是匿名的,您可能会拥有许多
MyClass$1
实例,每个实例在a
中具有不同的值。或者您可能根本没有实例。因此 getType() 唯一可以告诉您的是b
的声明类型,这正是它的作用。此时,b
字段实际上可能为null
,并且您仍然会得到Object
作为结果。Field 类提供 get() 方法来实际访问某个对象的特定字段,如下所示:
现在您得到类似
MyClass$1$1
的内容,它是该对象的匿名类的名称字段b
引用a
实例中的。Let's look at this line carefully:
First, your take the
a
variable. It is of some anonymous subclass of the Object. Let's call that classMyClass$1
. Okay, so far so good.Next, you call the getClass() method. It returns the class of a, that is, a description of the
MyClass$1
class. This description is not tied to any particular instance of that class, though. The class is the same for all instances, be ita
or whatever else (unless different class loaders are used). In this particular case, however, there can be only one instance, because the class is anonymous, but the mechanism is still the same.Now, from the class, you get the field
b
. As the class isn't directly tied to any of this instances, the field has nothing to do witha
either. It's just a description of what exactly the fielda
of the classMyClass$1
is.Now you get its type. But since it isn't tied to any instance, it can't know the runtime type. In fact, if the class wasn't anonymous, you could have numerous instances of
MyClass$1
, each having different value ina
. Or you could have no instances at all. So the only thing getType() can possibly tell you is the declared type ofb
, which exactly what it does. Theb
field could in fact benull
at that point, and you'd still getObject
as the result.The Field class provides the get() method to actually access that particular field of some object, like this:
Now you get something like
MyClass$1$1
, which is the name of the anonymous class of the object that fieldb
references to, in thea
instance.因为您获取的是字段“b”(对象)的类型,而不是您将实例分配给“b”的匿名内部类的类型。
你可以用这个
来代替。这获取了字段“b”的值及其类,但这仅在保证“b”不为空的情况下才有效。
这样做似乎表明设计不好,可能还有其他方法来归档您想要用它做的事情。但在不知道目的的情况下,我只能回答这些。
Because you are getting the type type of the field "b" (Object), not the type of the anonymous inner class of which you assigned the instance to "b".
You could use this
instead. This gets the value of the field "b" and it's class, but this only works if "b" is guaranteed be not null.
Doing this seems to indicate a bad design, there might be other ways to archive what you want to do with this. But without knowing the purpose, this is everything I can answer.