泛型列表<string>和列表<整数>表现不正常</integer> </string>

时间:2014-10-08 06:44:13

标签: java list generics arraylist

为什么println打印&#34; tom&#34;并且在转换为List<Integer>后没有显示任何运行时异常,而在转换为List<String>后无法打印值1?

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
    }
}

4 个答案:

答案 0 :(得分:34)

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

答案 1 :(得分:3)

这里的问题是java编译器在编译时选择方法,而不是运行时。 在编译时,它将选择方法PrintStream.print(String),而不是PrintStream.print(int)PrintStream.print(Object),两者都会成功。

答案 2 :(得分: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

因此,当您将非泛型列表分配给泛型列表时,它会被分配,但是当您打印它时,它会检查类型安全性或定义构造函数以进行强制转换,如果有有效和已定义的构造函数则打印出来,否则显示类强制转换异常由于缺少用于投射的未定义构造函数,因此无法投放该类。

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

答案 3 :(得分:0)

使用泛型可以避免这类问题,这是使用泛型的主要动机。

这是您的代码的实际流程,从您的第二个println()角度来看:

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

  2. 它向Integer添加StringArrayList

  3. 它将您的列表转换为String列表。您的列表标记为仅限String

  4. Java泛型只是一个编译时功能,因此您的列表可以接受没有任何问题的StringInteger元素。与编译器不同,对象本身对它所包含的类型一无所知。

    1. 它试图检索您的已转换列表的第一个元素,该元素应该是String并隐式地将其强制转换为String

    2. println(String x)班级拨打PrintStream

    3. 但是第一个元素实际上不是String而是Integer。 您无法将Integer转换为String

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