I'd wonder, if and how it is possible to achieve the below, while only beeing able to use the two class literal variables:
Class<Foo<Bar>> getFoobar(){
Class<Foo> fooClass = Foo.class;
Class<Bar> barClass = Bar.class;
// ... combine and return Class<Foo<Bar>>
}
... with the restriction, that it is not possible to use the types literally, but ok to retrieve the types programmatically from the class literal variables.
答案 0 :(得分:1)
我们不能使用类型参数(正如你已经注意到的那样),即我们不能指望像T.class
或new T()
这样的表达式可以工作,因为我们对泛型类型做不了多少“编程”。参数化类型在编译后会丢失其类型参数,因此对于Foo<T>
类型的以下实例:
Foo<String> foostr...;
Foo<Bar> foobar...;
我们将拥有相同的Class
对象,即
foostr.getClass() == foobar.getClass() == Foo.class
因此,允许Foo<String>.class
或Foo<Bar>.class
等类文字是没有意义的。
这就是编译类型下泛型类型的许多限制背后的原因:由于在运行时没有关于类型参数的信息(因为类型擦除),我们必须在编译时限制很多可能性
在运行时使用泛型类型的一种可能性是将有关类Foo
及其类型参数Bar
的信息提取为ParameterizedType
对象,例如
class Bar {
...
}
class Foo<T> {
...
}
class Foobar extends Foo<Bar> {
ParameterizedType getFoobar() {
return (ParameterizedType)getClass().getGenericSuperclass();
}
}
...
Foobar foobar = new Foobar();
System.out.println(foobar.getFoobar().getRawType()); // Foo.class
System.out.println(foobar.getFoobar().getActualTypeArguments()[0]); // Bar.class
另一种方法基于第一种方法,但更容易实现,是使用FasterXML Jacson Project中的TypeReference
(或创建自己的类)来捕获参数化类型:
class Foo<T> { ... }
class Bar { ... }
TypeReference typeReference = new TypeReference<Foo<Bar>>() {};
ParameterizedTypeImpl parametrizedType = (ParameterizedTypeImpl) typeReference.getType();
System.out.println(parametrizedType.getTypeName()); // Foo<Bar>
System.out.println(parametrizedType.getRawType()); // Foo
System.out.println(parametrizedType.getActualTypeArguments()[0]); // Bar
请详细了解ParameterizedTypeImpl#toString()
方法的实现。