添加到未知类型泛型列表的 Java

2022-09-04 01:14:22

我已经遇到了以前在Java中没有遇到过的事情,也就是说,我需要在运行时创建一个新的实例,比如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();

答案 1

不能在使用通配符泛型定义的集合中添加对象。此线程可能会对您有所帮助。

实际上,您正在创建一个集合,是的,每个集合的超类型,因此可以分配给任何泛型集合;但它太通用了,不允许任何类型的添加操作,因为编译器无法检查您正在添加的内容的类型。这正是泛型的含义:类型检查。

我建议你阅读这个话题,看看它也适用于你想做的事情。

您的集合太通用了,不允许添加任何内容。问题与附加的右侧(使用单例或反射)无关,它位于使用通配符的左侧声明类型中。


答案 2

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

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

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

这是理论上正确的方法。但谁在乎呢。我们都知道类型擦除,Java 不可能删除类型擦除并为类型参数添加运行时类型。因此,只要您知道自己在做什么,您就可以使用原始类型并自由投掷。