我有一个使用泛型的类。因为它需要对泛型类型的引用,所以构造函数具有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);

因为原始类型是参数化类型的超类型。

07-28 00:55
查看更多