我有一个使用泛型的类。因为它需要对泛型类型的引用,所以构造函数具有Class
参数(如this question中所述),因此看起来像这样:
MyGenericClass<T>
public MyGenericClass( final Class<T> valueClass ) {
this.clazz = valueClass;
}
现在,我想将MyGenericClass传递为T,但无法使其正常运行。
MyGenericClass<MyGenericClass<String>> foo =
new MyGenericClass<MyGenericClass<String>>(MyGenericClass<String>.class);
给我一个编译器错误。
看起来这是类型擦除的问题(请参阅this SO question)。有了这双层的泛型,我不确定是否可以做自己想做的事情。
有什么建议?
UTA:
我无法发布整个代码,因为它是公司代码,并且我不确定发布规则。该类实质上是一个MultipleValueMap,它将单个键映射到值列表。类对象用于创建列表中值的类型化数组(使用
list.toArray(T[])
)在这种情况下,我想拥有一个映射到多个值列表的键。这就是问题所在。
最佳答案
在这种情况下,泛型开始崩溃。 List<String>
是类型而不是类,因此只有List.class
。
番石榴的 TypeToken
是为这些情况而创建的。
class MyGenericClass<T> {
private Class<T> raw;
/* the code in this constructor
* has similar semantics to e.g.
* MyGenericClass<String>[] arr = new MyGenericClass[10];
* when passing a
* new TypeToken<MyGenericClass<String>>() {}
*/
MyGenericClass(TypeToken<T> type) {
@SuppressWarnings("unchecked")
final Class<T> unchecked = (Class<T>) type.getRawType();
raw = unchecked;
@SuppressWarnings("unchecked")
T[] arr = (T[]) Array.newInstance(type, 10);
//
}
}
MyGenericClass<MyGenericClass<String>> g =
new MyGenericClass<>(new TypeToken<MyGenericClass<String>>() {});
否则,您的选择将受到限制。有kludgy选项:
MyGenericClass<MyGenericClass<String>> g =
new MyGenericClass<MyGenericClass<String>>(
(Class) MyGenericClass.class);
也可能将
Class<T>
更改为Class<? extends T>
并传递一个子类(我看到有人已经发布了,所以我不会再重复它了)。如果您不需要将数组返回到外部世界,则可以执行以下操作:
class MyGenericClass<T> {
private Class<? super T> maybeSuper;
MyGenericClass(Class<? super T> maybeSuper) {
this.maybeSuper = maybeSuper;
// array which accepts T
Object[] arr = (Object[]) Array.newInstance(maybeSuper, 10);
}
}
然后,您可以执行以下操作:
MyGenericClass<MyGenericClass<String>> g =
new MyGenericClass<MyGenericClass<String>>(
MyGenericClass.class);
因为原始类型是参数化类型的超类型。