泛型集合

5

我有一个关于在集合中使用泛型的问题。

ArrayList<Integer> al=new ArrayList<Integer>();

我们知道上述代码意味着ArrayListal只能存放整数。因此,下一行代码会导致编译错误:
al.add("wwww");

但我不明白下面这行代码的意思,
ArrayList al=new ArrayList<Integer>();

在声明时,我们没有将 ArrayList<Integer> 放在左侧。现在,以下行不会导致编译错误:

al.add("wwww");

那么如果我这样声明:
ArrayList al=new ArrayList<Integer>();

这意味着a1可以接受任何类型吗?

这两种声明有什么区别?

6个回答

9

后一种声明(不带泛型)已经过时和不建议使用。您不应该使用它,它只是为了向后兼容而编译。现代IDE会在这里生成警告。

还要注意的是,Java仅在编译时强制执行泛型类型,因此在一些额外的转换中,您可以将不正确的类型添加到集合中。因此,最好始终保持使用泛型,并且不要绕过它们。


1
如果你正在使用IDE,它可能会对此显示警告。 - Axel
@Axel:+1。我独立地给我的答案添加了相同的评论,你必须相信我 ;-). - Tomasz Nurkiewicz
由于某种原因,从7版本开始,NetBeans的开发人员默认禁用了显示标准javac警告的功能。(并且明显增加了对实习生说“修复你的原始类型警告”的要求。) - Affe
它不仅仅是为了向后兼容而编译。如果没有这样的编译,许多集合框架在Java中将无法编写(除非使用JNI)。 - Ted Hopp
@TedHopp - 很有趣。因此,在某些情况下,仍然需要使用原始类型(而不是例如使用通配符)? - Paul Bellora
@PaulBellora 这篇Brian Goetz的论文中讨论了泛型的一些问题,非常有趣。链接 - Ted Hopp

5
使用以下代码:
ArrayList al = new ArrayList<Integer>();
a1.add("www");

编译器会生成一个警告(你应该注意!),但代码将不会出错。问题在于从a1中提取数据。如果你"知道"它包含整数值,那么你可以这样做:

Integer val = (Integer) a1.get(index);

但是当你遇到"www"元素时,你将会得到一个ClassCastException。泛型的目的是将这样的错误移动到编译时,而不是强制可怜的开发者追踪一个String值如何进入那个Integer数组列表。


0

你应该这样写:ArrayList<Integer> al=new ArrayList<Integer>();,以避免将其他类型的对象添加到列表中,因为你会在编译时看到错误。当然,你可以使用ArrayList al=new ArrayList<Integer>();,但是你必须小心。换句话说,总是使用第一个 :D


0

泛型是通过类型擦除实现的:泛型类型信息仅在编译时存在,之后被编译器擦除。所以,ArrayList al 声明允许编译器接受任何类型。这里有关于这个主题的Java文档


0
后一种声明基本上与以下相同:
ArrayList<Object> al=new ArrayList<Object>();

因此接受任何对象。它不应该被使用,而且可以使用,以便Java向后兼容(Java1.5之前)。


0

这种声明是为了向后兼容而允许的。因此,您可以将泛型列表传递给仅接受原始列表的旧式库中的方法:

List<Integer> list = new ArrayList<Integer>();
OldStyledClass.method(myArray);

方法声明如下:

public static void method(List list)...

在这种情况下,您可以在java.util.Collections中使用一些特殊的实用方法。因此,您可以将受保护的列表传递给此方法:
OldStyledClass.method(Collections.checkedList(myArray, Integer.class));

如果方法尝试将其他类型的对象放入列表中,您将立即收到ClassCastException。

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