ArrayList<Integer> 是否允许添加字符串?
Does ArrayList<Integer> allow adding of String?
我遇到了下面的代码,一个向 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
,我将不胜感激
您将新的 ArrayList 分配给了一个未类型化的列表。通用类型限制不适用于无类型列表,它可以让你在其中放入任何你想要的东西。编译器不会跟踪您的非类型化 List 引用了用泛型类型声明的内容。
无论如何这都不会产生 ClassCastException,泛型只影响编译。运行时
将类型放在列表变量上的情况:
List<Integer> list = new ArrayList<Integer>();
是首选,它应该会生成一个编译器错误,告诉您您在集合中放入了错误的类型。
在 this article 中描述了遗留、非通用代码和通用代码如何互操作:
In proper generic code, Collection would always be accompanied by a type parameter. When a generic type like Collection is used without a type parameter, it's called a raw type.
Most people's first instinct is that Collection really means Collection<Object>
. However, as we saw earlier, it isn't safe to pass a Collection<Part>
in a place where a Collection<Object>
is required. It's more accurate to say that the type Collection denotes a collection of some unknown type, just like Collection<?>
.
But wait, that can't be right either! Consider the call to getParts()
, which returns a Collection. This is then assigned to k, which is a Collection<Part>
. If the result of the call is a Collection<?>
, the assignment would be an error.
In reality, the assignment is legal, but it generates an unchecked warning. The warning is needed, because the fact is that the compiler can't guarantee its correctness. We have no way of checking the legacy code in getAssembly()
to ensure that indeed the collection being returned is a collection of Parts. The type used in the code is Collection, and one could legally insert all kinds of objects into such a collection.
So, shouldn't this be an error? Theoretically speaking, yes; but practically speaking, if generic code is going to call legacy code, this has to be allowed. It's up to you, the programmer, to satisfy yourself that in this case, the assignment is safe because the contract of getAssembly()
says it returns a collection of Parts, even though the type signature doesn't show this.
这是可能的,因为泛型在 Java 中的实现方式 - 使用 type erasure, and because Java supports raw types 向后兼容旧版本的 Java(1.4 及更早版本)。
泛型只存在于您的源代码中。编译器使用它们在编译时检查类型,然后丢弃泛型。在运行时,List<Integer>
只是一个 List
个对象,它不知道它是一个应该只包含 Integer
个对象的列表。
Java 支持使用原始类型,例如 List
而不是 List<Integer>
以向后兼容旧版本。当您使用原始类型时,就像您在上面的代码中所做的那样,您会收到编译器警告。您不应在新代码中使用原始类型 - 只有在需要处理无法更改的旧代码时才使用它们。
结合使用原始类型和类型擦除,您可以将不应该放入的对象类型放入列表中。
因为 List
在运行时对其元素应该具有的类型一无所知,所以它不会检查任何内容,因此您不会得到 ClassCastException
。
我遇到了下面的代码,一个向 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
您将新的 ArrayList 分配给了一个未类型化的列表。通用类型限制不适用于无类型列表,它可以让你在其中放入任何你想要的东西。编译器不会跟踪您的非类型化 List 引用了用泛型类型声明的内容。
无论如何这都不会产生 ClassCastException,泛型只影响编译。运行时
将类型放在列表变量上的情况:
List<Integer> list = new ArrayList<Integer>();
是首选,它应该会生成一个编译器错误,告诉您您在集合中放入了错误的类型。
在 this article 中描述了遗留、非通用代码和通用代码如何互操作:
In proper generic code, Collection would always be accompanied by a type parameter. When a generic type like Collection is used without a type parameter, it's called a raw type.
Most people's first instinct is that Collection really means
Collection<Object>
. However, as we saw earlier, it isn't safe to pass aCollection<Part>
in a place where aCollection<Object>
is required. It's more accurate to say that the type Collection denotes a collection of some unknown type, just likeCollection<?>
.But wait, that can't be right either! Consider the call to
getParts()
, which returns a Collection. This is then assigned to k, which is aCollection<Part>
. If the result of the call is aCollection<?>
, the assignment would be an error.In reality, the assignment is legal, but it generates an unchecked warning. The warning is needed, because the fact is that the compiler can't guarantee its correctness. We have no way of checking the legacy code in
getAssembly()
to ensure that indeed the collection being returned is a collection of Parts. The type used in the code is Collection, and one could legally insert all kinds of objects into such a collection.So, shouldn't this be an error? Theoretically speaking, yes; but practically speaking, if generic code is going to call legacy code, this has to be allowed. It's up to you, the programmer, to satisfy yourself that in this case, the assignment is safe because the contract of
getAssembly()
says it returns a collection of Parts, even though the type signature doesn't show this.
这是可能的,因为泛型在 Java 中的实现方式 - 使用 type erasure, and because Java supports raw types 向后兼容旧版本的 Java(1.4 及更早版本)。
泛型只存在于您的源代码中。编译器使用它们在编译时检查类型,然后丢弃泛型。在运行时,List<Integer>
只是一个 List
个对象,它不知道它是一个应该只包含 Integer
个对象的列表。
Java 支持使用原始类型,例如 List
而不是 List<Integer>
以向后兼容旧版本。当您使用原始类型时,就像您在上面的代码中所做的那样,您会收到编译器警告。您不应在新代码中使用原始类型 - 只有在需要处理无法更改的旧代码时才使用它们。
结合使用原始类型和类型擦除,您可以将不应该放入的对象类型放入列表中。
因为 List
在运行时对其元素应该具有的类型一无所知,所以它不会检查任何内容,因此您不会得到 ClassCastException
。