解析 TypeVariable
Resolve a TypeVariable
假设我有这些 classes:
class Container<T> {
private List<T> list;
}
我有一个 Container
的实例,比如
Container<?> instance = new Container<String>();
有没有办法找出 list
在 运行 时的实际类型参数?也就是说,它是 String
的 List
,而不是 java.lang.reflect.TypeVariable
的 List
].
我一直在查看 Java 的反射(field.getGenericType()
)、各种库(Guava Reflect, Typetools, ClassMate, even ASM 等),但我无法弄清楚。
我无法控制 Container
类型,因此无法向其添加任何字段。
我意识到由于擦除,这可能根本不可能,但如果可能的话,我不介意弄乱字节码。
编辑 我过度简化了我最初的问题。我有一条额外的信息可用;我也有这种:
class StringContainerContainer {
private Container<String> container;
}
(还有更多类似的类型,用于不同的通用参数。)
在 运行 时,我得到了上面提到的 instance
对象。通过对我的代码库进行一些重构,我还可以得到 StringContainerContainer
class(或任何相关的 *ContainerContainer
class),我可以用它来获得 java.lang.reflect.Field
对于 container
.
由于类型擦除,你不能这样做。使用反射最多只能获取有关已声明类型变量的信息,而不是在 运行 时间由实例绑定的实际类型。该信息被编译器丢弃。
有关详细信息,请阅读讨论类型擦除的 tutorial on Type Erasure and/or section 4.6 of the Java Language Specification。
如果您需要 run-time 有关实例的类型信息 class,您最好的办法是要求在实例构造时传递一个 Class
对象:
class Container<T> {
private List<T> list;
private Class<T> type;
public Container(Class<T> type) {
this.type = type;
}
}
通过你的编辑,是的,你可以发现 String
是实际的类型参数:
Field field = StringContainerContainer.class.getDeclaredField("container");
ParameterizedType gt = (ParameterizedType) field.getGenericType();
Class<?> arg = (Class<?>) gt.getActualTypeArguments()[0];
System.out.println(arg);
我应该指出,这标识了 StringContainerContainer
的 container
字段的类型参数。鉴于 Container
的编写方式,这也恰好是其 list
字段的类型参数,但该字段未被直接检查。
假设我有这些 classes:
class Container<T> {
private List<T> list;
}
我有一个 Container
的实例,比如
Container<?> instance = new Container<String>();
有没有办法找出 list
在 运行 时的实际类型参数?也就是说,它是 String
的 List
,而不是 java.lang.reflect.TypeVariable
的 List
].
我一直在查看 Java 的反射(field.getGenericType()
)、各种库(Guava Reflect, Typetools, ClassMate, even ASM 等),但我无法弄清楚。
我无法控制 Container
类型,因此无法向其添加任何字段。
我意识到由于擦除,这可能根本不可能,但如果可能的话,我不介意弄乱字节码。
编辑 我过度简化了我最初的问题。我有一条额外的信息可用;我也有这种:
class StringContainerContainer {
private Container<String> container;
}
(还有更多类似的类型,用于不同的通用参数。)
在 运行 时,我得到了上面提到的 instance
对象。通过对我的代码库进行一些重构,我还可以得到 StringContainerContainer
class(或任何相关的 *ContainerContainer
class),我可以用它来获得 java.lang.reflect.Field
对于 container
.
由于类型擦除,你不能这样做。使用反射最多只能获取有关已声明类型变量的信息,而不是在 运行 时间由实例绑定的实际类型。该信息被编译器丢弃。
有关详细信息,请阅读讨论类型擦除的 tutorial on Type Erasure and/or section 4.6 of the Java Language Specification。
如果您需要 run-time 有关实例的类型信息 class,您最好的办法是要求在实例构造时传递一个 Class
对象:
class Container<T> {
private List<T> list;
private Class<T> type;
public Container(Class<T> type) {
this.type = type;
}
}
通过你的编辑,是的,你可以发现 String
是实际的类型参数:
Field field = StringContainerContainer.class.getDeclaredField("container");
ParameterizedType gt = (ParameterizedType) field.getGenericType();
Class<?> arg = (Class<?>) gt.getActualTypeArguments()[0];
System.out.println(arg);
我应该指出,这标识了 StringContainerContainer
的 container
字段的类型参数。鉴于 Container
的编写方式,这也恰好是其 list
字段的类型参数,但该字段未被直接检查。