2011-06-29 25 views
10

我已经进入了一些我以前没有遇到过的Java,也就是说,我需要在运行时创建一个新的实例来说明ArrayList类,而不指定已知类型,然后将数据添加到列表中。这听起来有点含糊所以这里有一个例子:Java添加到未知类型的通用列表

Class<?> c = i.getClass(); 

Constructor<?> con = ArrayList.class.getConstructor(); 
ArrayList<?> al = (ArrayList<?>)con.newInstance(); 

al.add("something"); 

我现在做这个而不只是使用泛型的理由是因为仿制药已经被大量使用和“我”在这个例子中的变量将被给予用作类型“?”。我真的不想扔另一个通用的,因为这会给用户带来更多的工作,并且在最终设计中会更不灵活。有什么方法可以使用下面的东西(注意:下面的东西不起作用)。任何人有想法?

ArrayList<c> al = (ArrayList<c>)con.newInstance(); 
+3

泛型用于编译时验证。在运行时,你可能不用担心泛型类型,只是使用非泛型的'ArrayList'。 –

+0

@Bala R你说得对,我可以删除泛型,我只是想知道是否有办法将它从类中拉出来以确保验证。谢谢,你的想法可能会为我的目的。 – ars265

+0

我不得不问,列表的目的是什么,你不知道它将包含的数据的类型? – Bringer128

回答

7

您不能在使用通配符泛型定义的集合中添加对象。 This thread可能会帮助你。事实上,你正在创建一个集合,是的,每个集合的超类型,因此可以分配给任何泛型集合;但是它太泛化了,不允许任何类型的添加操作,因为编译器无法检查您添加的内容的类型。这正是泛型的意义所在:类型检查。

我建议你阅读这篇文章,看看它也适用于你想做的事。

您的集合太泛化,无法添加任何东西。问题与asignment的右侧无关(使用单例或反射),它使用通配符在左侧声明类型中。

5

如果我明白你的意思,你有一个C类,它在编译时是未知的,你想创建一个ArrayList<C>,类型安全的方式。这是可能的:

Class<?> c = ...; 
ArrayList<?> al = listOf(c); 

static <T> ArrayList<T> listOf(Class<T> clazz) 
{ 
    return new ArrayList<T>(); 
} 

这是做它的理论上正确的方法。但谁在乎。我们都知道类型擦除,并且Java不会放弃类型擦除并为类型参数添加运行时类型。所以只要你知道你在做什么,你就可以使用原始类型并自由投射。

+1

是的,你可以创建一个未知的通用ArrayList,但是你不能添加一些东西,这是我的问题发挥的地方。 – ars265

+0

这与ArrayList al = new ArrayList ();'有什么区别? – newacct

+1

@newacct大概是,有一个带外协议,在某些时候,列表可以安全地(通过应用程序逻辑)转换为'ArrayList ',并且向其中添加一个'X'对象。擦除,演员和添加都不是问题。具体化是另一回事。 – irreputable

4

你可以使用ArrayList<Object>,你可以add()任何东西。

+1

是的,但之后它们是对象类型的,不再是未知类型。这将工作,只要添加,但返回铸造的对象ArrayList。用户然后将不得不将每一个回来。现在,从1.4开始,我相信,Java确实保留了它们的子类中的额外数据,但并不能满足我需要的。 – ars265

+0

@ ars265:但是由于在编译时你不知道类型,所以无论如何你必须将它抛弃 – newacct

+0

@newacct:这是真的,但我正在开发一个框架,以便框架的用户可以收到结果。我正在寻找一些有点不同的东西。我最终为环境构建了一个linq类类。 – ars265

相关问题