使用通用集合

时间:2013-07-30 09:37:16

标签: java generics collections arraylist

它已成功编译并运行

List a=new ArrayList<String>();
a.add(new Integer(5));

有人可以解释一下吗?

6 个答案:

答案 0 :(得分:6)

原因是您声明变量a是原始列表,即List没有任何关联类型:

List a = new ArrayList<String>();

就此而言,即使这样也会编译和运行:

List a = new ArrayList<Date>();
a.add(new Integer(5));

此处还有关于genericstype erasure的说明:

泛型由Java编译器实现为称为擦除的前端转换。 类型擦除适用于泛型的使用。使用泛型时,它们会转换为编译时检查和运行时类型转换。

由于类型擦除机制,此代码:

List<String> a = new ArrayList<String>();
a.add("foo");
String x = a.get(0);

编译成:

List a = new ArrayList();
a.add("foo");
String x = (String) a.get(0);

与您的代码类似:

List a = new ArrayList<String>();
a.add(new Integer(5));

被编译成这个(由于类型擦除):

List a = new ArrayList();
a.add(new Integer(5));

因此不会生成编译或运行时错误。

但是,当您尝试从列表中获取项目时,您会注意到区别:

int i = a.get(0); // compilation error due to type mismatch

这是因为您的列表被声明为原始类型。要避免此错误,您需要使用泛型来声明列表,或者像上面那样执行类型转换。即。

在列表中使用泛型类型:

List<Integer> a = new ArrayList<Integer>();
a.add(new Integer(5));    
int i = a.get(0);

或者做这个演员:( 不推荐

List a=new ArrayList<Date>();
a.add(new Integer(5));
int i = (Integer) a.get(0);

PS:请注意,在运行时无法找到特定类型,例如String用于声明列表对象。

答案 1 :(得分:1)

您没有在实际定义中指定泛型类型

如果你写了

List<String> a = new ArrayList<String>();
a.add(new Integer(5));

不会编译。

答案 2 :(得分:1)

你应该做

List<String> a = new ArrayList<String>();
a.add(new Integer(5));
  • List表示编译器将检查是否仅将String个对象添加到集合中。
  

有人可以解释一下吗?

这是可能的,因为

  • 由于类型为erasuse,在运行时没有类型安全
  • 语句List a表示没有编译时检查列表中添加了哪些对象。

从java 7开始,您不必为类型安全编写List<String> a = new ArrayList<String>()。您可以使用菱形运算符并使用List<String> a = new ArrayList();

实现相同的功能

答案 3 :(得分:1)

List a是一种缺乏泛型的原始类型。这与您能够向其添加整数的原因完全相同。

要强制执行正确的行为,请将List更改为使用泛型。

List<String> a

答案 4 :(得分:1)

编译后会删除通用数据。这意味着

List<String> a=new ArrayList<String>();

将更改为您在下面的类文件

中看到的内容
List a=new ArrayList();

现在回答您的问题,a的类型为List原始列表,您可以添加任何。泛型用于放置编译时限制。这意味着说你有

List<String> a=new ArrayList<String>();

此行将生成编译时错误

a.add(new Integer(1)); //error

答案 5 :(得分:1)

这是因为旧的遗留代码被允许放置任何东西(除了 原语)成集合。并且为了支持遗留代码,Java 5和Java 6 允许您的新型安全代码使用旧代码。

因此,Java 5或Java 6编译器被迫让您编译新类型 安全代码即使你的代码调用一个较旧的类的方法需要一个 非类型安全论证,谁知道它是什么。

实际上编译器会警告你。编译器从编译中生成了一个完全有效的类文件,但它很友善地告诉你,用这么多的话来说,“我真的希望你知道你在做什么,因为这段旧代码对您的<String>打字没有任何尊重(甚至知识),并且可以为您珍贵的ArrayList<String>做任何他想做的事。“