2014-10-08 75 views
19

为什么println打印“汤姆”,而不是表示铸造到List<Integer>之后的任何运行时异常,而这是无法铸造List<String>后打印值1?泛型列表<String>和列表<Integer>不表现为预期的

import java.util.Arrays; 
import java.util.List; 

public class Main { 
    public static void main(String args[]) { 

     List list = Arrays.asList(1, "tom"); 

     System.out.println(((List<Integer>) list).get(1)); 
     // "tom" 

     System.out.println(((List<String>) list).get(0)); 
     // ClassCastException: Integer cannot be cast to String 
    } 
} 
+5

它*显示运行时异常。 – Maroun 2014-10-08 06:54:56

+0

每次注释一种类型的列表以获得期望的输出,即,列表 list3 = list1; // System.out.println(list3.get(0)); – Aman 2014-10-08 06:56:46

回答

34

println第一个电话被静态地分派到PrintStream.println(Object)和第二呼叫被分派到PrintStream.println(String)。因此,对于第二次调用,编译器会将隐式强制转换为String,然后在运行时由ClassCastException失败。

+3

这就是正确答案+1。 – Maroun 2014-10-08 07:00:23

+2

可否请您详细说明这一点,bcoz我认为在第一种情况下,如果它打印PrintStream.println(整数)PrintStream.println(字符串)的第二种情况或这两个shud有PrintStream.println(对象)。 – Aman 2014-10-08 07:06:21

+7

没有'PrintStream.println(Integer)'。编译器总是调度到具有最特定签名的方法。 'Integer'的最具体类型是'Object','String'的最具体类型是'String'。 – ZhekaKozlov 2014-10-08 07:10:13

0
Integer i = new Integer(101); 
String s = new String(i); // undefined and Invalid 
StringBuffer sb = new StringBuffer(i); // defined and Valid 

String s2 = "tom"; 
Integer i2 = new Integer(s2); //defined and valid 

所以,当你指定一个非泛型列表到一个通用的一个是分配,但是当你打印它会检查类型安全或定义铸造构造是否有有效的和定义的构造函数,然后它被其他印刷由于缺少用于强制转换的未定义构造函数,因此类无法投射,因此显示了类转换异常。

如果我错了,请帮我用正确的逻辑...

+0

这与构造函数无关。 – Radiodef 2014-10-08 15:42:47

0

这种类型的问题可以通过使用泛型来避免,并且是使用泛型的主要动机。

这是您的代码的实际流量,从第二个println()点:

  1. 您的代码声明Object类型的ArrayList;

  2. 它向ArrayList添加了IntegerString

  3. 它将您的列表投到String列表中。您的列表被标记为仅限于String

Java泛型是编译时功能只让你列表可以没有任何问题StringInteger元素接受。与编译器不同,对象本身不知道它包含的类型。

  • 它attemps中检索其应该是一个String并且将它转换为String隐式的铸造列表的第一个元素。

  • 致电println(String x)PrintStream类。

  • 但是这第一个元素其实不是String而是Integer。 您不能将Integer转换为String

    阅读Generics in Java动机部分示例。

    相关问题