public class Foo<T> {
}
public class Bar<T> {
private final Class<T> clazz;
public Bar(Class<T> clazz) {
this.clazz = clazz;
}
}
我尝试做的事情是这样的:
Bar<Foo<?>> bar = new Bar<>(Foo.class);
当然,这并不起作用,因为Foo不是Foo<?>
。问题是如何建造这样一个酒吧?我需要完全Bar<Foo<?>>
,而不是Bar<Foo>
,因为有一种方法只接受Bar<Foo<?>>
作为参数。欣赏想法。
答案 0 :(得分:3)
抱歉,没有这样的Class
对象,因为正如您所说,擦除意味着无法进行。你需要施展它:
((Class<Foo<?>>)(Class)Foo.class)
这将为您提供所需的边界,但可能会生成编译器警告,因为您正在执行未经检查的通用转换。这是合理的:编译器要求您承认您将遗漏了泛型的编译时安全性。但是在这种情况下,这种情况确实无法在程序中或将来生成运行时错误,所以没关系。
双重转换是必要的,因为编译器知道Foo.class与Class&gt;不兼容,所以你必须先将它转换为“raw”类型Class:在表达式中使用原始类型会禁用编译器的泛型 - 对这个表达式进行类型检查,这样“不可能”的演员阵容就可以了。
答案 1 :(得分:1)
如果不在<>
中提供类型信息,则无法创建通用对象,如问题帖子所示。您必须提供类型或使用原始版本。如果您被迫使用通配符参数类型,则只需使用原始类型来禁止警告,如下所示
@SuppressWarnings("rawtypes")
Bar<Foo<?>> bar = new Bar(Foo.class);
//Bar is having no type "<>" (but this is not recommended
答案 2 :(得分:0)
由于java.lang.Class是不可变的,你可以在Bar的构造函数中使用较弱的类型声明:
class Foo<T> {}
class Bar<T> {
private final Class<? extends T> clazz;
public Bar(Class<? extends T> clazz) {
this.clazz = clazz;
}
}
如果您仍然需要字段为Class<T>
而不是Class<? extends T>
,则可以在构造函数中将其强制转换。