14

我想知道Java中是否有办法做类似的事情

Class c = List<String>.class;
Class c2 = List<Date>.class;

我需要这样的东西来创建一个存储类名(具有泛型类型)和我以后可以查找的相应对象的映射。例如,

Map<Class, Object> dataMap = new HashMap<Class, Object>();
dataMap.put(c, listOfStrings);
dataMap.put(c2, listOfDates);

由于运行时类型擦除,这是不可能的吗?

4

3 回答 3

15

你不能完全像这样,但你可以使用与 Guice 相同的方法来实现你的总体目标TypeLiteral。如果您已经在使用 Guice,我建议您直接使用它 - 否则,您可能想要创建自己的类似类。

本质上,这个想法是指定类型参数的泛型类型的子类直接保留该信息。所以你写了这样的东西:

TypeLiteral literal = new TypeLiteral<List<String>>() {};

然后你可以使用literal.getClass().getGenericSuperclass()并从中获取类型参数。TypeLiteral本身不需要有任何有趣的代码(我不知道它在 Guice中是否有任何东西,出于其他原因)。

于 2012-04-21T08:33:39.533 回答
5

不,这是不可能的。您甚至无法List<String>.class在代码中引用 - 它会导致编译错误。对于 ,只有一个类对象List,它被称为List.class

由于运行时类型擦除,这是不可能的吗?

正确的。

顺便说一句,这是泛型类型,而不是带注释的类型。

更新

再想一想,您可以通过稍微调整 Josh Bloch 的类型安全异构容器(在Effective Java 2nd Ed.,Item 29 中发布)来获得与上面的 Map 相当接近的东西:

public class Lists {
    private Map<Class<?>, List<?>> lists =
            new HashMap<Class<?>, List<?>>();

    public <T> void putList(Class<T> type, List<T> list) {
        if (type == null)
            throw new NullPointerException("Type is null");
        lists.put(type, list);
    }

    public <T> List<T> getList(Class<T> type) {
        return (List<T>)lists.get(type);
    }
}

演员表getList未经检查,发出警告,但恐怕我们无法避免。但是,我们知道为 class 存储的值X必须是 a List<X>,因为这是由编译器保证的。所以我认为演员阵容是安全的(如果你遵守规则,也就是说 - 即永远不要putList使用普通的非泛型Class参数调用),因此可以使用@SuppressWarnings("unchecked").

你可以像这样使用它:

Lists lists = new Lists();
List<Integer> integerList = new ArrayList<Integer>();
List<String> stringList = new ArrayList<String>();
...

lists.putList(Integer.class, integerList);
lists.putList(String.class, stringList);
List<Integer> storedList = lists.getList(Integer.class);

assertTrue(storedList == integerList);
于 2012-04-21T08:28:48.107 回答
1

这是不可能的,因为你正在尝试。
但是您可以装饰这些列表并创建一个MyListDatesandMyListString并将它们存储在哈希图中

于 2012-04-21T08:31:02.037 回答