Java:在嵌套参数化类型中获取内部类型(反射)

时间:2010-02-16 13:55:21

标签: java generics reflection nested

关于Java中类型擦除处理的大多数文档假定用例正在处理类似SomeType<ParamType>的类型。 我正在尝试处理以下方法的方法参数:

public void setOtherReferenceRanges(List<ReferenceRange<T>> referenceRanges)

当使用类型DvQuantity实例化容器类时,此签名应该成为 运行时public void setOtherReferenceRanges(List<ReferenceRange<DvQuanitity>> referenceRanges)

使用反射可以看到List的{​​{1}}为actualTypeArgument。由于反射使用类信息,我不希望它给我ReferenceRange<T>。 但是,当我创建包含此方法的类时,我将ReferenceRange<DvQuantity>类型作为DvQuantity传递。因此,T中的类型填充应该可供Java运行时使用,但我找不到获取它的方法。我最终得到了一个通过反射访问的T对象,它似乎不包含任何有用的数据。

您能想到在运行时发现此信息的任何方法吗?

3 个答案:

答案 0 :(得分:1)

当你说

  

当我创建包含此方法的类

我猜您的意思是在创建该类型的对象时,例如:

foo = new ContainerClass<DvQuantity>();

在这种情况下,由于删除,无法恢复DvQuantity类型。

但是,如果你创建一个将类型参数传递给超类,就像这样

class DvQuantityContainerClass extends ContainerClass<DvQuantity> {...}
...
foo = new DvQuantityContainerClass();

或者,更短,一个内联匿名子类(看起来几乎像第一个例子,但有一个微妙但重要的区别):

foo = new ContainerClass<DvQuantity>(){};

然后,您可以恢复type参数,因为您恢复了用于在运行时扩展超类的类型参数。遗憾的是,Java本身并没有提供一种简单的方法来获取填充了DvQuantityContainerClass.setOtherReferenceRanges的{​​{1}}方法的类型。为此,我编写了gentyref来做高级操作对泛型类型的反思:

T

答案 1 :(得分:0)

通用类型信息是erased by the compiler,在运行时不可用。当我需要在运行时确保某种类型时,我传入一个类参数:

public <T> void doSomething(T t, Class<T> c);

这并不总是方便甚至可能,但在很多情况下都是可能的。

答案 2 :(得分:0)

  

因此,T的类型填充应该可用于Java运行时,但我找不到获取它的方法。

也许这不完全正确,但我想到的方式是在运行时没有实际的类 - 只是一个没有特定类型的对象,它符合T的接口。换句话说,擦除不是与对象发生的,而是与这些模糊的(至少在OOP世界中)类型的东西。

http://java.sun.com/docs/books/tutorial/java/generics/erasure.html

有一些方法可以捕获类本身内部的类型信息(T类型需要一个方法getUnderlyingType()...或者其他东西),但这是一个坏主意。如果你真的需要原始类型的对象,我会重新考虑使用泛型。