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

Rah*_*hul 12 java generics

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

Class c = List<String>.class;
Class c2 = List<Date>.class;
Run Code Online (Sandbox Code Playgroud)

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

Map<Class, Object> dataMap = new HashMap<Class, Object>();
dataMap.put(c, listOfStrings);
dataMap.put(c2, listOfDates);
Run Code Online (Sandbox Code Playgroud)

这是不可能的,因为运行期间的类型擦除?

Jon*_*eet 12

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

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

TypeLiteral literal = new TypeLiteral<List<String>>() {};
Run Code Online (Sandbox Code Playgroud)

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

  • 番石榴12(一周或两周)将有'TypeToken`,它具有相同的作用,尽管有更多的铃声和口哨声. (3认同)

Pét*_*rök 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

演员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);
Run Code Online (Sandbox Code Playgroud)