我想知道,是否以及如何能够实现以下目标,同时只能使用两个类文字变量:
Class<Foo<Bar>> getFoobar(){
Class<Foo> fooClass = Foo.class;
Class<Bar> barClass = Bar.class;
// ... combine and return Class<Foo<Bar>>
}
...有限制,不可能按字面意思使用类型,但可以通过编程方式从类字面量变量中检索类型。
最佳答案
我们不能从字面上使用类型参数(正如您已经正确注意到的那样),即我们不能期望像 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
另一种方法基于第一种方法,但更容易实现,是使用 TypeReference
(或创建您自己的类)从 FasterXML Jacson 项目捕获参数化类型:
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()
的实现即可详细方法。
关于java - 如何从两个现有的类文字构造参数化类文字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45507258/