Java泛型和数组初始化

18

以下是相应的解释:

public class GenericsTest {
    //statement 1
    public ArrayList<Integer>[] lists;

    public GenericsTest()
    {
            //statement 2
        lists = new ArrayList<Integer>[4];
    }
}
编译器接受语句1。编译器会标记语句2为“通用数组创建”。关于禁止使用通用数组的一个好解释是这篇文章,认为由于数组是协变的,而泛型则不是,如果允许通用数组,则可以破坏通用类型。无论如何,撇开争论是否应该采取极端措施来创建这种复杂的不一致性以防止出现问题(如果有人知道任何有关此问题的优缺点的好讨论,请发布,我会很感兴趣),为什么语句1能够被允许而语句2不能?
4个回答

6

这是因为你无法创建它们,但你可以使用它们:

public class GenericsTest {
    //statement 1
    public ArrayList<Integer>[] lists;

    public GenericsTest()
    {
        //statement 2
        lists = new ArrayList[4];
        //statement 3
        lists[0].add(new Integer(0));
        //statement 4
        lists[0].add(new String(""));
    }
}

语句3是可行的,语句4将导致编译器错误。


语句4确实会出现错误,但语句2会发出“未经检查的转换”警告,如果值得的话。 - nsayer
1
实际上,我认为语句3的行为将是不确定的,因为您还没有先执行“lists [0] = new ArrayList <Integer>();”。 - Evan
嗯,不错的建议。这个例子实际上是可以编译通过的(如果你忽略第4条语句),但我还没有运行它。第3条语句会导致 RuntimeException。 - Sven Lilienthal

1

好的参考资料,谢谢。我想我需要再仔细研究一下这个。 - Steve B.

0

所以实际问题是:为什么声明泛型数组时没有错误?

只有在出现错误时才会得到错误提示。在没有技术问题的情况下添加错误提示只会增加混乱(尽管编辑器可能会指出这一点)。

在某些情况下,您可能希望通过未经检查的转换来放宽规则。除了指出愚蠢之外,没有必要强制让代码充斥着更多的警告抑制。


-1
在这种情况下,我会避免使用数组,就是因为这个原因。您原始代码中的“列表”声明可以是:
List<List<Integer>> lists = new ArrayList<List<Integer>>(4);
for(int i = 0; i < 4; i++) lists.add(null); // or add an empty ArrayList<Integer>

在变量声明中,应使用接口而不是实现。

除此之外,您应该使用get()或set()代替数组[]语法。除此之外,它们是等效的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接