Java 解析类型变量

Java 解析类型变量,java,reflection,bytecode-manipulation,Java,Reflection,Bytecode Manipulation,假设我有这些课程: class Container<T> { private List<T> list; } 有没有办法在运行时找出列表的实际类型参数?也就是说,它是字符串列表,而不是java.lang.reflect.TypeVariable列表 我一直在研究Java的reflection field.getGenericType、各种库、甚至等等,但我搞不清楚 我无法控制容器类型,因此无法向其中添加任何字段 我意识到,由于擦除的原因,这可能根本不可能实现,尽管如

假设我有这些课程:

class Container<T> {
  private List<T> list;
}
有没有办法在运行时找出列表的实际类型参数?也就是说,它是字符串列表,而不是java.lang.reflect.TypeVariable列表

我一直在研究Java的reflection field.getGenericType、各种库、甚至等等,但我搞不清楚

我无法控制容器类型,因此无法向其中添加任何字段

我意识到,由于擦除的原因,这可能根本不可能实现,尽管如果可能的话,我不介意把字节码弄乱

编辑我过度简化了我的初始问题。我有一个额外的信息可用;我也有这种类型:

class StringContainerContainer {
  private Container<String> container;
}
还有一些类似的类型,用于不同的泛型参数


在运行时,我得到了上面提到的实例对象。通过对代码库进行一点重构,我还可以访问StringContainerContainer类或任何与之相关的*ContainerContainer类,我可以使用它来获取容器的java.lang.reflect.Field。

由于类型擦除,您无法执行此操作。使用反射最多只能获取有关已声明类型变量的信息,而不是运行时实例绑定的实际类型。这些信息被编译器丢弃了

有关更多信息,请阅读和/或,其中讨论类型擦除

如果需要有关实例类的运行时类型信息,最好是要求在实例构造时传递类对象:

class Container<T> {
    private List<T> list;
    private Class<T> type;

    public Container(Class<T> type) {
        this.type = type;
    }
}

通过编辑“是”,您可以发现字符串是实际的类型参数:

Field field = StringContainerContainer.class.getDeclaredField("container");
ParameterizedType gt = (ParameterizedType) field.getGenericType();
Class<?> arg = (Class<?>) gt.getActualTypeArguments()[0];
System.out.println(arg);

我应该指出,这标识了StringContainerContainer的容器字段的类型参数。考虑到容器是如何编写的,这也恰好是其列表字段的类型参数,但该字段没有直接检查。

查看所有答案:简短答案:不,不可能。在运行时,对象甚至不知道自己的泛型类型。嗯,那太糟糕了。当我发现,在某些情况下,你可以得到类型回来,我得到了我的希望:。顺便说一句,我对容器没有控制权,所以很遗憾,在容器中添加一个字段是不可能的。我将更新我的问题以反映这一点。
Field field = StringContainerContainer.class.getDeclaredField("container");
ParameterizedType gt = (ParameterizedType) field.getGenericType();
Class<?> arg = (Class<?>) gt.getActualTypeArguments()[0];
System.out.println(arg);