[英]Java type inference with erasure
在擦除和类型推断方面遇到一些问题。 我有以下的类层次结构,看起来并不十分复杂:
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<?>>
作为参数。 欣赏想法。
抱歉,没有这样的Class
对象,因为正如您所指出的,擦除意味着不可能。 您需要强制转换:
((Class<Foo<?>>)(Class)Foo.class)
这将为您提供所需的界限,但可能会产生编译器警告,因为您正在执行未经检查的泛型转换。 这是合理的:编译器要求您确认您遗漏了泛型的编译时安全性。 但是在这种情况下,实际上在这种情况下,无论是在您的程序中还是在将来,这种情况都不会产生运行时错误,所以很好。
双播是必要的,因为编译器知道Foo.class与Class>不兼容,因此您必须首先将其转换为“原始”类型Class:在表达式中使用原始类型会禁用编译器的泛型检查这样的表达方式,那么“不可能”的转换就可以了。
如问题帖所示,如果不在<>
提供类型信息,就无法创建通用对象。 您必须提供Type或使用原始版本。 如果您被迫使用通配符参数类型,则只需使用原始类型抑制警告,如下所示
@SuppressWarnings("rawtypes")
Bar<Foo<?>> bar = new Bar(Foo.class);
//Bar is having no type "<>" (but this is not recommended
由于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>
Class<? extends T>
,将其强制转换为构造函数是安全的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.