创建泛型集合数组

2022-09-02 10:50:45

实际上,问题应该是

Creating an array of generic anything.

为什么编译器不能处理它?

以下内容将被标记为错误 - 无法创建泛型数组。

List<MyDTO>[] dtoLists = {new ArrayList<MyDTO>(), anExistingDtoList};

为了克服这一点,我需要

List<MyDTO>[] dtoLists = (List<MyDTO>[])Array.newInstance(ArrayList.class, 2);
dtoLists[0] = new ArrayList<MyDTO>();
dtoLists[1] = anExistingDtoList;

那么,为什么编译器不能将第一种情况转换为第二种情况呢?

我确实意识到泛型是编译时确定的而不是运行时确定的,而数组是运行时确定的,因此需要确定的类型才能创建数组。

编译器设计人员会遇到哪些技术/逻辑障碍,这些障碍会阻止他们实现这一点?

这个问题纯粹是哲学上的,关于语言的正交性吗?如果是这样,这种行为如何违反语言正交性?

这是一个复杂性问题吗?解释复杂性。

我希望我的问题的答案能让我更好地了解Java编译器在涉及泛型时的行为。

附注:c'mon停止被触发快乐。泛型列表的答案数组没有回答我的问题。为什么编译器不能自发地执行转换?


答案 1

实际上Java确实为varargs创建了通用数组,所以你可以这样做

List<MyDTO>[] dtoLists = array(new ArrayList<MyDTO>(), anExistingDtoList);

@SafeVarargs
static <E> E[] array(E... array)
{
    return array;
}

至于为什么显式泛型数组创建是被禁止的,它与类型擦除有关。(上述解决方案中存在相同的问题,但被 抑制)然而,这是值得商榷的。有不同的方法来处理这个问题,编译器警告可能就足够了。但是他们选择完全禁止它,可能是因为数组不再重要,因为现在我们有了通用集合。@SafeVarargs


答案 2

我确实知道,相对于这个问题的解决方法,Array.newInstance()是一种昂贵的调用方法。IIRC 它使用本机方法来实例化数组,同时进行其他反射。我无法提供任何统计数据,但这似乎是一个足够好的理由,使编译器不会自动替换这些功能,以便允许创建泛型数组。特别是考虑到 等的存在,这似乎不是一个紧迫的问题。ArrayList


推荐