我可以在Java中使用泛型类型调用.class吗?

时间:2012-04-21 08:22:49

标签: java generics

我想知道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);

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

3 个答案:

答案 0 :(得分:12)

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

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

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

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

答案 1 :(得分:5)

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

  

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

正确。

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

更新

第二个想法,你可以通过调整Josh Bloch的类型安全的异类容器(发表于 Effective Java 2nd Ed。,Item 29一点:

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中的演员阵容未经检查,发出警告,但恐怕我们无法避免。但是,我们知道为类X存储的值必须是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);

答案 2 :(得分:1)

这是不可能的,因为你正在尝试 但您可以decorate 这些列表,然后创建MyListDatesMyListString,并将它们存储在hashmap中