13
List list = new ArrayList<String>() ;
list.add(1) ;
Integer hello = (Integer) list.get(0) ;
System.out.println(hello);

上面的代码有一个List类型的引用,它引用了String类型的ArrayList的一个实例。执行该行时,不是将 1 添加到 ArrayList (of type String) 吗?如果是,那么为什么允许这样做?list.add(1)

4

8 回答 8

15

您使用了类型擦除,这意味着您忽略了之前设置的通用检查。你可以摆脱这个,因为泛型是一个编译时特性,在运行时不检查。

你有什么和你一样

List list = new ArrayList() ;
list.add(1) ;
Integer hello = (Integer) list.get(0) ;
System.out.println(hello);

或者

List<Integer> list = new ArrayList<Integer>() ;
list.add(1) ;
Integer hello = list.get(0); // generics add an implicit cast here
System.out.println(hello);

如果您查看编译器生成的字节码,则无法区分。

有趣的是,你可以这样做

List<String> strings = new ArrayList<String>();
@SuppressWarnings("unchecked");
List<Integer> ints = (List) strings;
ints.add(1);

System.out.println(strings); // ok
String s= strings.get(0); // throws a ClassCastException
于 2013-04-25T14:51:00.947 回答
12

问题是您的list变量具有原始类型,您可以将任何类型的对象添加到此列表中。要解决该问题,只需将其声明为Listof String

List<String> list = new ArrayList<String>() ;
于 2013-04-25T14:51:56.317 回答
3

它编译是因为声明List list使用原始类型List,而不是绑定类型List<String>。第二行编译,因为你的list变量可以接受任何东西。第三行编译,因为list.get(0)返回Object。第四行没有失败的理由。

意外的是,编译代码中没有任何内容导致 Integer 1 被强制转换为String. 但你不能依赖它。如果第一行是正确的

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

你的错误会在编译时被发现。

于 2013-04-25T14:54:22.007 回答
3

当您声明这样的列表时: List list = new ArrayList<String>() ;

您正在使用所谓的原始类型。它是一种具有泛型类型参数的类型,例如 List,但您未能提供一个。如果您检查编译器警告,您会看到它告诉您这一点。将参数化类型与原始类型混合通常被认为是编程错误。还行吧:

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

这没关系(但已过时):

List list = new ArrayList();

但是应该避免使用您编写它的方式。

问题是泛型只在编译器时检查,你告诉编译器List,不是List<String>,所以它会让你把任何你想要的东西放在那里!右侧有参数这一事实并没有真正的意义,它是实际引用的类型对编译器很重要。

于 2013-04-25T14:54:25.490 回答
0
List list = new ArrayList<String>() ; // WARNING!!!

一个不安全的 List 是指一个安全的 ArrayList

list.add(1) ;  // WARNING!!!

一个整数(int 1 转换为整数是自动装箱)而不是添加到列表中的字符串

Integer hello = (Integer) list.get(0) ;

强制转换是必需的,因为 unsafe List 可以包含任何内容。

System.out.println(hello);

调用 Integer.toString()

当行 list.add(1) 被执行时,不是 1 添加到 ArrayList (of type String) 吗?

是的。Integer 被添加到应该包含 String 的 ArrayList 中。

如果是,那么为什么允许这样做?

向后兼容性。Java 必须支持预通用代码。

列表列表;意味着它是不安全的,所以你可以用它做任何事情,并且被引用的 ArrayList() 必须容忍它。

道德:不要忽略编译器警告,否则整数可能会进入应该包含字符串的 ArrayList。

于 2013-04-25T15:05:47.347 回答
-1

是的... 1 被添加到 Array 中,因为 Java 与其他语言一样,实现了原始数据类型的隐式(自动)转换(强制转换)。

更多信息在这里转换和促销

于 2013-04-25T14:56:10.593 回答
-3

尝试这个

List.add(Integer.toString(1));

你也可以试试这个

List list = new ArrayList<Object>() ;

如果不需要arraylist必须是String的Arraylist

于 2013-04-25T14:51:31.697 回答
-4

不,因为 Java 将1视为整数。您需要先将您的号码转换为字符串Integer.toString(n)

于 2013-04-25T14:50:19.673 回答