java - 为什么传递给 List 参数的 List<Integer> 上的 add(String) 不抛出异常?

标签 java generics

为什么可以插入 String进入List<Integer>在下面的代码中?我有一个将数字插入整数列表的类:

public class Main {    
    public static void main(String[] args) {        
        List<Integer> list = new ArrayList<Integer>();
        list.add(2);
        list.add(3);
        list.add(4);

        Inserter inserter = new Inserter();
        inserter.insertValue(list);
        System.out.print(list);        
    }
}

然后我有一个单独的类,它插入一个 String进入List , 带有数字字符串值 "42" :

public class Inserter {    
    void insertValue(List list)
    {
        list.add(new String("42"));
    }
}

为什么编译器不引发编译器错误,或者运行时抛出运行时异常,例如*CastException ,当我添加 String到整数列表?另外,为什么 System.out.print(list)产生如下输出而不抛出任何异常?

[2, 3, 4, 42]

让这一切发生的根本原因是什么?

最佳答案

这可能是一个示例,用于说明泛型的 type erasure(我建议阅读该链接以完全理解这一点以及它在 Java 泛型中扮演的关键角色)。

  1. list 声明为 List<Integer>
  2. 当它作为参数传递给 listValue 时,它被转换为 raw type
  3. 从此时开始,在该方法中,程序在运行时不知道它最初是一个“整数列表”,因此它可以无一异常(exception)地插入任何对象——在类声明中,类型变量被删除为 Object
  4. 在 main 方法中,print 命令只是调用列表中的 toString,它不关心它包含的内容,因此它会打印包括字符串在内的元素。

如果你想看到异常,尝试添加一行:

Integer myInt = list.get(3); // try to get the string

这将抛出 ClassCastException,因为编译器会在删除期间在必要时插入强制转换以保护类型安全。

参数化类型(例如 List<Integer> )转换为原始类型(例如 List )会给您一个编译器警告,告诉您这种问题可能即将发生。您可以使用 @SuppressWarnings("unchecked") (或 "rawtypes" ,如果它是 available to you )来抑制该警告。这是一种“确认”您将要执行的操作会导致未经检查的运行时异常的好方法,并且还有助于告诉其他 future 的编码人员可能会发生一些奇怪的事情。例如:

void insertValue(@SuppressWarnings("unchecked") List list)
{
    list.add(new String("42"));
}

关于java - 为什么传递给 List 参数的 List<Integer> 上的 add(String) 不抛出异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28236967/

相关文章:

java - 选中时显示 JTable 行的信息

java - 为什么java中的类需要序列化

java - 如何将 List<实现接口(interface)的对象> 传递给方法?

c# - 尝试调用 function<T> where T : TheClass, new() where T: class

java selenium webdriver - 如何输出 javascript 对象的属性?

java - 从 jboss fusion 控制台中删除了 Fabric

java - 为什么这个 JSF 表达式不起作用?

java - 如何在Scala中实现扩展Comparable且没有特定类型的Java接口(interface)?

java - 泛型和 Java8 Streams 的未经检查的调用错误

java - 如何制作一个合并任何类型数组的通用方法?