【问题标题】:Does ArrayList<Integer> allow adding of String?ArrayList<Integer> 是否允许添加字符串?
【发布时间】:2015-07-30 01:30:36
【问题描述】:

我遇到了下面的代码,一个简单的给List添加元素的例子

    List list = new ArrayList<Integer>();
    ListIterator<Integer> litr = null;
    list.add("A");

    list.add("1");

    list.add(5);

    litr = list.listIterator();
    while(litr.hasNext()){
        System.out.println("UIterating " + litr.next());
    }

我希望它会抛出一个ClassCastException,但它却把它写到了控制台

A
1
5

这看起来很奇怪。当我尝试时:

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

我得到一个编译时错误。

如果有人能解释如何将 String 对象添加到 ArrayList 中,我将不胜感激

【问题讨论】:

标签: java generics arraylist collections


【解决方案1】:

您将新的 ArrayList 分配给了一个无类型的 List。通用类型限制不适用于无类型列表,它可以让您在其中放入任何您想要的内容。编译器不会跟踪您的无类型列表是否引用了使用泛型类型声明的内容。

在任何情况下这都不会产生 ClassCastException,泛型只会影响编译。在运行时

将类型放在列表变量上的情况:

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

是首选,它应该会生成一个编译器错误,告诉您在集合中放入了错误的类型。

this article 中有关于旧版、非泛型代码和泛型代码如何互操作的描述:

在适当的泛型代码中,Collection 总是伴随着一个类型参数。当像 Collection 这样的泛型类型在没有类型参数的情况下使用时,它被称为原始类型。

大多数人的第一直觉是 Collection 真正的意思是Collection&lt;Object&gt;。然而,正如我们之前看到的,在需要Collection&lt;Object&gt; 的地方传递Collection&lt;Part&gt; 是不安全的。更准确地说,Collection 类型表示某个未知类型的集合,就像Collection&lt;?&gt;

但是等等,这也不对!考虑对getParts() 的调用,它返回一个集合。然后将其分配给 k,即Collection&lt;Part&gt;。如果调用的结果是Collection&lt;?&gt;,那么赋值就会出错。

实际上,分配是合法的,但它会产生未经检查的警告。需要警告,因为事实是编译器无法保证其正确性。我们无法检查 getAssembly() 中的遗留代码以确保返回的集合确实是 Parts 的集合。代码中使用的类型是Collection,可以合法地将各种对象插入到这样的集合中。

那么,这不应该是一个错误吗?从理论上讲,是的;但实际上,如果通用代码要调用遗留代码,则必须允许这样做。这取决于你,程序员,让你自己确信,在这种情况下,赋值是安全的,因为 getAssembly() 的合约说它返回一个 Parts 的集合,即使类型签名没有显示这一点。

【讨论】:

  • 仅供参考:您应该将代码块放在引号中的代码周围。否则,您将看不到其中一个 Collections 是 Collection&lt;Part&gt;
  • @NathanHughes 感谢您的回答。了解无类型列表和原始集合
【解决方案2】:

这可能是因为泛型在 Java 中的实现方式 - 使用 type erasure,并且因为 Java 支持 raw types 以向后兼容 Java 的旧版本(1.4 和更早版本)。

泛型仅存在于您的源代码中。编译器使用它们在编译时检查类型,然后丢弃泛型。在运行时,List&lt;Integer&gt; 只是对象的List,它不知道它是一个应该只包含Integer 对象的列表。

Java 支持使用 List 等原始类型而不是 List&lt;Integer&gt;,以向后兼容旧版本。当您使用原始类型时,正如您在上面的代码中所做的那样,您会收到编译器警告。您不应该在新代码中使用原始类型 - 只有在需要处理无法更改的旧代码时才使用它们。

原始类型和类型擦除的组合允许您将对象类型放入您不应该放入的列表中。

因为List 在运行时不知道其元素应该具有的类型,所以它不检查任何内容,因此您不会得到ClassCastException

【讨论】:

    猜你喜欢
    • 2015-05-27
    • 2015-07-22
    • 2015-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-13
    相关资源
    最近更新 更多