public class Main {
public static void main(String[] args) {
ArrayList<Integer> ar = new ArrayList<Integer>();
List l = new ArrayList();
l.add("a");
l.add("b");
ar.addAll(l);
System.out.println(ar);
}
}
输出:[a,b]
您不能直接将String
添加到ArrayList<Integer> ar
,但通过使用addAll()
是可能的。
如何将String
添加到类型已经被指定为Integer
的ArrayList
中?谁能强调清楚的实现细节和背后的原因?
发布于 2015-03-24 13:05:59
但是我们如何才能将类型已经指定为
的字符串添加到arraylist中呢?
由于Java泛型被设计为向后兼容的方式,基本上具有类型擦除和原始类型。
在执行时,没有ArrayList<Integer>
这样的东西--只有一个ArrayList
。您使用的是原始类型List
,因此编译器不会执行任何常规检查,无论是在编译时还是添加执行时强制转换。
编译器会警告你,你正在做不安全的事情:
Note: Main.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
..。当你使用相关的标志重新编译时,它会警告所有的事情,包括可能最令人惊讶的一行:
ar.addAll(l);
这是在编译方面让我有点惊讶的一个--我相信它实际上相信List
是一个Collection<? extends Integer>
,而我们知道它不是。
如果你避免使用原始类型,这种混乱就会消失。
发布于 2015-03-25 05:02:06
这更多的是关于Java类型系统中原始类型和泛型类型的混合,而不是类型擦除。让我补充一下问题中的代码片段:
ArrayList<Integer> ar = new ArrayList<Integer>();
List l = new ArrayList(); // (1)
l.add("a");
l.add("b");
ar.addAll(l); // (2)
System.out.println(ar);
Integer i = ar.get(0); // (3)
对于今天删除的泛型,第(3)行抛出了ClassCastException
。如果Java的泛型被具体化,很容易假设运行时类型检查会导致在第(2)行抛出异常。这将是具体化泛型的一种可能的设计,但其他设计可能不会进行这种检查。为什么不行?主要原因与我们今天删除泛型的原因相同:迁移兼容性。
Neal Gafter在他的文章中观察到,泛型的使用有很多不安全的地方,不正确的类型转换,等等。今天,即使在引入泛型十多年后,我仍然看到很多原始类型的用法。(不幸的是,包括这里的Stack Overflow。)无条件地执行具体化的泛型类型检查会破坏大量的代码,这当然会对兼容性造成很大的打击。
任何现实的通用具体化提案都必须在选择加入的基础上提供具体化,例如通过子类型(如Gafter的提案),或通过注释(Gerakios,Biboudis,Smaragdakis )。 PDF GPSE 2013.),它必须决定如何处理原始类型。完全禁止原始类型似乎是完全不切实际的。反过来,允许原始类型实际上意味着有一种方法可以绕过泛型类型系统。
(这种决定不是轻率做出的。我亲眼目睹了两位类型理论家之间的争吵,其中一位抱怨说,Java的类型系统是不健全的。对于类型理论家来说,这是最严重的侮辱。)
本质上,这就是这段代码所做的:它通过使用原始类型绕过了泛型类型检查。即使Java的泛型被具体化,检查也可能无法在第(2)行完成。在一些具体化的泛型设计下,代码的行为可能与现在完全一样:在第(3)行抛出异常。
在Jon Skeet's answer中,他承认,在第(2)行,编译器相信list l
包含正确类型的元素,这让他有些惊讶。这并不是真正的信任问题--毕竟,编译器确实会在这里发出警告。更多的是编译器会说,“好吧,你在使用原始类型,你得靠自己。如果你后来得到了一个ClassCastException
,那不是我的错。”同样,这是为了兼容目的而允许原始类型,而不是擦除。
发布于 2015-03-24 13:05:50
您正在使用原始类型。如果你使用List<String> l = new ArrayList<>()
,你会发现你的代码不能再编译了。原始类型的存在只是为了向后兼容,不应该在新代码中使用。
https://stackoverflow.com/questions/29233225
复制