我之前遇到过一些我以前没有遇到的东西,也就是说,我需要在运行时创建一个新的ArrayList类实例而不分配已知类型然后将数据添加到列表中。这听起来有点模糊,所以这是一个例子:
Class<?> c = i.getClass();
Constructor<?> con = ArrayList.class.getConstructor();
ArrayList<?> al = (ArrayList<?>)con.newInstance();
al.add("something");
现在我这样做而不仅仅是使用泛型的原因是因为泛型已经被大量使用而且这个例子中的“i”变量将被用作类型“?”。我真的不想投入另一个通用,因为这会给用户带来更多的工作,并且在最终设计中会更不灵活。有没有办法使用下面的东西(注意:下面的内容不起作用)。有人有想法吗?
ArrayList<c> al = (ArrayList<c>)con.newInstance();
答案 0 :(得分:11)
您无法在使用通配符泛型定义的集合中添加对象。 This thread可能会对您有所帮助。
实际上,您正在创建一个集合,是的,每个集合的超类型,因此,可以分配给任何泛型集合;但它太通用了,不允许任何类型的添加操作,因为编译器无法检查你要添加的内容的类型。而这正是泛型的意思:类型检查。
我建议你阅读帖子,看看它也适用于你想做的事情。
你的集合过于通用,无法添加任何内容。问题与asignment的右侧无关(使用单例或反射),它位于使用通配符的左侧声明类型中。
答案 1 :(得分:8)
如果我明白你的意思,你就有了一个C类,它在编译时是未知的,你想以类型安全的方式创建一个ArrayList<C>
。这是可能的:
Class<?> c = ...;
ArrayList<?> al = listOf(c);
static <T> ArrayList<T> listOf(Class<T> clazz)
{
return new ArrayList<T>();
}
这是理论正确的做法。但谁在乎。我们都知道类型擦除,并且Java不会丢弃类型擦除并为类型参数添加运行时类型。因此,只要您知道自己在做什么,就可以使用原始类型并自由投射。
答案 2 :(得分:5)
您可以使用ArrayList<Object>
,add()
任何内容。