首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ArrayList<Integer>采用字符串

ArrayList<Integer>采用字符串
EN

Stack Overflow用户
提问于 2015-03-24 20:55:20
回答 6查看 2.3K关注 0票数 32
代码语言:javascript
运行
复制
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添加到类型已经被指定为IntegerArrayList中?谁能强调清楚的实现细节和背后的原因?

EN

回答 6

Stack Overflow用户

发布于 2015-03-24 21:05:59

但是我们如何才能将类型已经指定为

的字符串添加到arraylist中呢?

由于Java泛型被设计为向后兼容的方式,基本上具有类型擦除和原始类型。

在执行时,没有ArrayList<Integer>这样的东西--只有一个ArrayList。您使用的是原始类型List,因此编译器不会执行任何常规检查,无论是在编译时还是添加执行时强制转换。

编译器会警告你,你正在做不安全的事情:

代码语言:javascript
运行
复制
Note: Main.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

..。当你使用相关的标志重新编译时,它会警告所有的事情,包括可能最令人惊讶的一行:

代码语言:javascript
运行
复制
ar.addAll(l);

这是在编译方面让我有点惊讶的一个--我相信它实际上相信List是一个Collection<? extends Integer>,而我们知道它不是。

如果你避免使用原始类型,这种混乱就会消失。

票数 50
EN

Stack Overflow用户

发布于 2015-03-25 13:02:06

这更多的是关于Java类型系统中原始类型和泛型类型的混合,而不是类型擦除。让我补充一下问题中的代码片段:

代码语言:javascript
运行
复制
    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,那不是我的错。”同样,这是为了兼容目的而允许原始类型,而不是擦除。

票数 8
EN

Stack Overflow用户

发布于 2015-03-24 21:05:50

您正在使用原始类型。如果你使用List<String> l = new ArrayList<>(),你会发现你的代码不能再编译了。原始类型的存在只是为了向后兼容,不应该在新代码中使用。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29233225

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档