【问题标题】:Is it possible to get elements of a Collection (e.g. List) using reflection [in Java]是否可以使用反射 [in Java] 获取集合的元素(例如列表)
【发布时间】:2017-01-15 06:34:47
【问题描述】:

我已经完成了我的研究,但我仍然无法调用它是否可能。这个问题听起来像是一个特例。然而,我试图尽可能地概括它。

在 Java 中,我知道可以使用反射来公开对象的字段(比如x)。而且我知道可以更深入地公开子对象的字段,例如x 的字段。但是,当涉及到通用对象时,这变得很棘手。

为了更好地解释这一点,假设我们有以下两个简单的类:

package reflection;

import java.util.*;

public class Subject {

    public List<SomeUserDefinedObj> myListOfObj =
            new ArrayList<SomeUserDefinedObj>();

    public SomeUserDefinedObj singleObj = new SomeUserDefinedObj();

    public Subject(){
        myListOfObj.add(new SomeUserDefinedObj());
    }

}

package reflection;

public class SomeUserDefinedObj {

    public int x;

}

我们有以下测试类,它将通过反射检查Subject

package reflection;

import java.lang.reflect.*;

public class Test {

    public static void main(String[] args) {
        Subject subject = new Subject();

        Class<?> c = subject.getClass();   
        for (Field field:c.getDeclaredFields()){
            System.out.println("Field in " + c.getName() + ": " + field.getName());

            Class<?> nestedClass = field.getType();
            for (Field nestedField:nestedClass.getDeclaredFields()){
                System.out.println("\tField in " + nestedClass.getName() + ": " + nestedField.getName());
            }
        }        
    }
}

这个测试的输出是:

Field in reflection.Subject: myListOfObj
Field in reflection.Subject: singleObj
    Field in reflection.SomeUserDefinedObj: x

现在,我们可以看到检索到单个对象的内容,但列表好像是空的。我知道有一些方法可以使用对象本身的实例来获取列表的类型(您可以从中迭代列表中的对象),例如subject 来自 Test 喜欢 here。例如,我可以做Object myInstance = field.get(subject); 并且从他们我将能够确定列表中元素的类型并迭代它们(经过测试和工作)。

但是,(在这里我的问题可能是具体的)我无权访问该实例(由于使用遗留代码而设计阻止了这种奢侈)。所以,我试图通过只使用反射类对象来实现这个目标,例如c 来自 Test。我找到了一些资源,可以帮助我确定列表中元素的类型,例如herehere(我测试了它们并且它们有效)。然而,这个(第一)并没有授予实际类型,因为该类型可能是一个抽象类,(第二)我看不到任何从那里获取列表元素信息的方法,无论类型是否是抽象的。据我了解,检索给定此方法的类型只能保证它将返回给您使用列表初始化的类型,而不是元素(甚至类型可能不准确,如解释的那样)。

最后,鉴于我所说的所有情况(仅使用反射对象而不是实际实例对象)。 那么,问题就变成了,是否可以在不使用反射访问实际实例的情况下检索 Collection 元素?

【问题讨论】:

  • 一般情况下不会。编译时泛型存储在源代码和accessible through reflection 中,但泛型本身是erased at compile time,因此您无法访问运行时泛型类型。这意味着您可以在示例中访问 Collection 的类型,因为它是“硬编码”的 - 如果 class SubjectCollection 的类型中是通用的,这是不可能的。
  • 扩展 Collection 的泛型类和用户定义的泛型类型类有什么区别。我问这个是因为,在我的一个测试中,我尝试创建自己的泛型类型类(它拥有并返回一个类型并没有什么花哨的)。并且使用上面示例中的反射,我能够检索它的元素!
  • 重点是,如果您有somewhere 编写了实际的泛型类型,那么您可以通过类型参数跟踪它以计算出运行时泛型类型。这在现实中可能极其复杂,并且通常不可能,因为某些泛型类型是在运行时确定的——例如反序列化的东西。一个很好的例子参见 Spring 的GenericTypeResolver - 开源和测试代码是一个很好的信息来源。

标签: java generics reflection collections


【解决方案1】:

字段仅具有对应类的特定实例的值。

所以简单的答案是:没有实例,您无法访问字段的值(除非该字段是状态)。

想象一个类代表一个盒子的蓝图。当你现在对这样一个盒子的内容感兴趣时......你仍然需要一个真正的盒子来查看。

但是:当您能够在运行您的应用程序的同一个 JVM 中执行代码时......那么它可能会以某种方式访问​​它们。您需要找出您已知的其他对象是否可以包含您想要查看的那些框。

【讨论】:

  • 没错,但在示例中List&lt;SomeUserDefinedObj&gt;class 的属性,因此您可以通过反射获取其泛型类型。这在一般情况下是不正确的。
  • 我不明白的是,字段是基于“真实”实例创建的,因此我几乎没有尝试从它们那里获取所有信息而不返回实际实例。关于您的第二点,我想到了这一点,但问题是我没有太多关于列表字段中元素的信息(例如名称或字节码)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-12
相关资源
最近更新 更多