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)
您使用了类型擦除,这意味着您忽略了之前设置的通用检查。你可以摆脱这个,因为泛型是一个编译时特性,在运行时不检查。
你有什么和你一样
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
问题是您的list
变量具有原始类型,您可以将任何类型的对象添加到此列表中。要解决该问题,只需将其声明为List
of String
:
List<String> list = new ArrayList<String>() ;
它编译是因为声明List list
使用原始类型List
,而不是绑定类型List<String>
。第二行编译,因为你的list
变量可以接受任何东西。第三行编译,因为list.get(0)
返回Object
。第四行没有失败的理由。
意外的是,编译代码中没有任何内容导致 Integer 1 被强制转换为String
. 但你不能依赖它。如果第一行是正确的
List<String> list = new ArrayList<>();
你的错误会在编译时被发现。
当您声明这样的列表时:
List list = new ArrayList<String>() ;
您正在使用所谓的原始类型。它是一种具有泛型类型参数的类型,例如 List,但您未能提供一个。如果您检查编译器警告,您会看到它告诉您这一点。将参数化类型与原始类型混合通常被认为是编程错误。还行吧:
List<String> list = new ArrayList<String>() ;
这没关系(但已过时):
List list = new ArrayList();
但是应该避免使用您编写它的方式。
问题是泛型只在编译器时检查,你告诉编译器List
,不是List<String>
,所以它会让你把任何你想要的东西放在那里!右侧有参数这一事实并没有真正的意义,它是实际引用的类型对编译器很重要。
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。
是的... 1 被添加到 Array 中,因为 Java 与其他语言一样,实现了原始数据类型的隐式(自动)转换(强制转换)。
更多信息在这里转换和促销
尝试这个
List.add(Integer.toString(1));
你也可以试试这个
List list = new ArrayList<Object>() ;
如果不需要arraylist必须是String的Arraylist
不,因为 Java 将1
视为整数。您需要先将您的号码转换为字符串Integer.toString(n)