从整数列表的索引打印字符串

时间:2018-01-02 11:52:32

标签: java generics raw-types

我正在运行这一小段代码:

List<String> abc = new ArrayList<String>();
abc.add("something");
List raw = abc;
List<Integer> def = raw;
System.out.println(def.get(0));

我不明白为什么在将包含String成员的列表分配给Integer列表时不会抛出异常。此外,Integer列表如何存储和打印String?有人可以帮助我吗?

2 个答案:

答案 0 :(得分:4)

这就是你不应该使用原始类型的原因。

当你这样做时

List raw = abc;

你自己用列表擦除类型。所以它们没有类型,也没有编译器的错误。要获得泛型的好处,您应该避免使用原始类型。

还要考虑阅读Type Erasing。在运行时,列表不知道它们的类型。类型会被删除,它们只会获得列表中的任何内容。

您预期的错误是编译器错误,同时您避免首先提供类型。因此没有错误。

如果您确实想要查看异常,请尝试将当前列表中的元素分配给整数。虽然编译器不会给你任何错误,但在运行时类型会匹配并且你会遇到异常。

如果查看Raw Types docs,您会看到几乎相同的示例

Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8);  // warning: unchecked invocation to set(T)
  

警告显示原始类型绕过泛型类型检查,将不安全代码的捕获推迟到运行时。因此,您应该避免使用原始类型。

答案 1 :(得分:4)

当您编写System.out.println(def.get(0));时,您将从ArrayList中获取第一个元素并将其传递给System.out.println

我猜您会期待一个异常,因为def.get(0) 假设返回Integer,尽管它在运行时实际返回String但是 System.out.println接受Object,它同时接受StringInteger,对于参数类型为哪种方法无关紧要。这意味着在运行时,在尝试将返回值传递给方法之前,不会对返回的值进行转换。

如果您尝试将get返回的值实际存储到Integer类型的变量中,或者调用类型为Integer的参数的方法,则只会导致异常导致演员阵容发生:

System.out.println(def.get(0)); // works
Integer integer = def.get(0); // java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
doSomething(def.get(0)); // java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

private static void doSomething(Integer i) {}