Java 反映嵌套匿名类

发布于 2024-10-19 14:21:23 字数 403 浏览 2 评论 0原文

为什么这段代码返回“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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云仙小弟 2024-10-26 14:21:23

因为 b 被声明为 Object

public Object b = ...;

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

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

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

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

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

Because b is declared as Object:

public Object b = ...;

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 (since a is declared as Object and therefore b is not visible as its member you have to use reflection to access it):

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

UPDATE: You can't reflect c without accessing the instance of object containing it. That's why these types are called anonymous - a type containing c has no name, so that you can't declare field b as a field of that type.

懷念過去 2024-10-26 14:21:23

让我们仔细看看这一行:

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

首先,获取 a 变量。它是 Object 的某个匿名子类。我们将该类命名为 MyClass$1。好的,到目前为止一切顺利。

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

现在,您可以从类中获取字段 b。由于该类不直接绑定到任何此类实例,因此该字段也与 a 无关。它只是对类 MyClass$1 的字段 a 到底是什么的描述。

现在你得到了它的类型。但由于它不绑定到任何实例,因此它无法知道运行时类型。事实上,如果该类不是匿名的,您可能会拥有许多 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 实例中的

Let's look at this line carefully:

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

First, your take the a variable. It is of some anonymous subclass of the Object. Let's call that class MyClass$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 it a 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 with a either. It's just a description of what exactly the field a of the class MyClass$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 in a. Or you could have no instances at all. So the only thing getType() can possibly tell you is the declared type of b, which exactly what it does. The b field could in fact be null at that point, and you'd still get Object as the result.

The Field class provides the get() method to actually access that particular field of some object, like this:

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

Now you get something like MyClass$1$1, which is the name of the anonymous class of the object that field b references to, in the a instance.

蝶…霜飞 2024-10-26 14:21:23

为什么inner-inner类型会丢失?

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

如何反映 c 字段?

你可以用这个

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

来代替。这获取了字段“b”的值及其类,但这仅在保证“b”不为空的情况下才有效。

这样做似乎表明设计不好,可能还有其他方法来归档您想要用它做的事情。但在不知道目的的情况下,我只能回答这些。

Why does the inner-inner type get lost?

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".

How can I reflect the c field ?

You could use this

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文