该代码不应该总是抛出一个ClassCastException
吗?它适用于我使用 Sun Java 6 编译器和运行时(在 Linux 上)。您将 s 转换Integer
为String
s。创建的迭代器将是 an Iterator<String>
,但随后它尝试访问第一个元素,即 an Integer
,因此失败。
如果您像这样更改数组,这会变得更清楚:
return Arrays.asList("one", 2, 3);
现在循环实际上适用于第一个元素,因为第一个元素是 aString
并且我们看到了输出;然后Iterator<String>
第二个失败,因为它不是字符串。
如果您只使用泛型List
而不是特定的,您的代码就可以工作:
List list = getObjects();
for (Object o : list) {
System.out.println(o);
}
...或者,当然,如果您使用List<Integer>
, 因为内容是Integer
s。你现在所做的会触发编译器警告Note: Generics.java uses unchecked or unsafe operations.
——而且是有充分理由的。
此修改也有效:
for (Object o : (List)list)
...大概是因为那时您正在处理的是Iterator
,而不是Iterator<String>
.
bozho 说他在 Windows XP 上没有看到这个错误(没有提到哪个编译器和运行时,但我猜是 Sun 的),你说你没有看到它(或不可靠),所以很明显有一些这里的实现敏感性,但底线是:不要用于List<String>
与 a List
of Integer
s 交互。:-)
这是我正在编译的文件:
import java.util.Arrays;
import java.util.List;
public class Generics {
static List getObjects() {
return Arrays.asList("one", 2, 3);
}
public static void main(String[] args) {
List<String> list = getObjects();
for (Object o : list) { // ClassCastException?
System.out.println(o);
}
}
}
这是编译:
tjc@forge:~/temp$ javac Generics.java
注意:Generics.java 使用未经检查或不安全的操作。
注意:使用 -Xlint:unchecked 重新编译以获取详细信息。
这是运行:
tjc@forge:~/temp$ java 泛型
一
线程“主”java.lang.ClassCastException 中的异常:java.lang.Integer 无法转换为 java.lang.String
在Generics.main(Generics.java:12)
第 12 行是for
语句。请注意,它确实输出了第一个元素,因为我将其更改为String
. 它没有输出其他的。(在我做出改变之前,它立即失败了。)
这是我正在使用的编译器:
tjc@forge:~/temp$ which javac
/usr/bin/javac
tjc@forge:~/temp$ ll /usr/bin/javac
lrwxrwxrwx 1 root root 23 2010-09-30 16:37 /usr/bin/javac -> /etc/alternatives/javac*
tjc@forge:~/temp$ ll /etc/alternatives/javac
lrwxrwxrwx 1 root root 33 2010-09-30 16:37 /etc/alternatives/javac -> /usr/lib/jvm/java-6-sun/bin/javac*
这是反汇编,它显示了checkcast
:
tjc@forge:~/temp$ javap -c 泛型
编译自“Generics.java”
公共类泛型扩展 java.lang.Object{
公共泛型();
代码:
0:aload_0
1:调用特殊#1;//方法 java/lang/Object."":()V
4:返回
静态 java.util.List getObjects();
代码:
0:iconst_3
1:新数组#2;//类java/io/Serializable
4:重复
5:iconst_0
6:最不发达国家#3;//字符串一
8:商店
9:重复
10:iconst_1
11:iconst_2
12:调用静态#4;//方法 java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
15:商店
16:重复
17:图标st_2
18:图标st_3
19:调用静态#4;//方法 java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
22:商店
23:调用静态#5;//方法 java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
26:返回
公共静态无效主(java.lang.String[]);
代码:
0:调用静态#6;//方法getObjects:()Ljava/util/List;
3:astore_1
4:aload_1
5:调用接口#7、1;//接口方法 java/util/List.iterator:()Ljava/util/Iterator;
10:astore_2
11:加载_2
12:调用接口#8、1;//接口方法 java/util/Iterator.hasNext:()Z
17:如果当量 40
20:aload_2
21:调用接口#9、1;//接口方法 java/util/Iterator.next:()Ljava/lang/Object;
26:检查广播#10;//类java/lang/String
29:astore_3
30:获取静态#11;//字段 java/lang/System.out:Ljava/io/PrintStream;
33:加载_3
34:调用虚拟#12;//方法java/io/PrintStream.println:(Ljava/lang/Object;)V
37:转到 11
40:返回
}
不过,底线必须是:不要使用 aList<String>
与List
包含非String
s 内容的 a 交互。:-)