这段代码难道不应该总是抛出ClassCastException吗?在我使用Sun Java 6编译器和运行时(在Linux上)时,它会抛出异常。您正在将Integer转换为String。创建的迭代器将是一个Iterator<String>,但然后它试图访问第一个元素,即一个Integer,因此失败。
如果您像这样更改数组,则情况会变得更清晰:
return Arrays.asList("one", 2, 3);
现在循环实际上对于第一个元素起作用,因为第一个元素是一个 String
并且我们看到了输出;然后 Iterator<String>
在第二个元素时失败了,因为它不是一个字符串。
如果你只使用一个通用的 List
而不是特定的列表,则您的代码将起作用:
List list = getObjects();
for (Object o : list) {
System.out.println(o);
}
如果您使用的是List<Integer>
,因为内容是Integer
,那么您当然可以这样做。您现在所做的会触发编译器警告,原因很明显:注意:Generics.java使用未经检查或不安全的操作。
以下修改也有效:
for (Object o : (List)list)
......这可能是因为此时您正在处理的是一个Iterator
,而不是Iterator<String>
。
bozho说他在Windows XP上没有看到这个错误(没有提及使用哪个编译器和运行时,但我猜测是Sun的),而您说您没有看到它(或者不太可靠),所以显然这里存在一些实现上的敏感性,但底线是:不要使用List<String>
与List
中的Integer
交互。 :-)
这是我正在编译的文件:
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) {
System.out.println(o);
}
}
}
以下是编译结果:
tjc@forge:~/temp$ javac Generics.java
注意:Generics.java使用了未经检查或不安全的操作。
注意:请使用-Xlint:unchecked重新编译以获取详细信息。
以下是运行结果:
tjc@forge:~/temp$ java Generics
one
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at 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
从 "Generics.java" 编译而来
public class Generics extends java.lang.Object{
public Generics();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return
static java.util.List getObjects();
Code:
0: iconst_3
1: anewarray #2; //class java/io/Serializable
4: dup
5: iconst_0
6: ldc #3; //String one
8: aastore
9: dup
10: iconst_1
11: iconst_2
12: invokestatic #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
15: aastore
16: dup
17: iconst_2
18: iconst_3
19: invokestatic #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
22: aastore
23: invokestatic #5; //Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
26: areturn
public static void main(java.lang.String[]);
Code:
0: 调用静态方法 #6; //Method getObjects:()Ljava/util/List;
3: astore_1
4: aload_1
5: 调用接口方法 #7, 1; //InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
10: astore_2
11: aload_2
12: 调用接口方法 #8, 1; //InterfaceMethod java/util/Iterator.hasNext:()Z
17: 如果为假跳转到40行
20: aload_2
21: 调用接口方法 #9, 1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
26: 强制类型转换为 #10; //class java/lang/String
29: astore_3
30: 获取静态字段 #11; //Field java/lang/System.out:Ljava/io/PrintStream;
33: aload_3
34: 调用虚方法 #12; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
37: 跳转到11行
40: return
}
总之,不要使用 List<String>
与包含非 String
的 List
进行交互。:-)
java.lang.ClassCastException: XXXX cannot be cast to YYYY
。 (2)行号有时会偏差几行,因此请查看上下报告行数的几行,以寻找异常来源可能性。 - Bert Fcheckcast
在某些已编译版本(例如我的版本和Tim在使用1.6.0_21时的版本)中存在,而在其他版本(例如bozho和您的版本)中不存在,这真是令人着迷。 - T.J. Crowder