Java 为什么';t在列表中添加(字符串)<;整数>;传递给列表参数是否引发异常?

Java 为什么';t在列表中添加(字符串)<;整数>;传递给列表参数是否引发异常?,java,generics,Java,Generics,为什么可以将字符串插入以下代码中的列表?我有一个类将数字插入整数列表: 公共类主{ 公共静态void main(字符串[]args){ 列表=新的ArrayList(); 增加(2); 增加(3); 增加(4); 插入器插入器=新插入器(); inserter.insertValue(列表); 系统输出打印(列表); } } 然后我有一个单独的类,它将一个字符串插入到列表中,数值字符串值为“42”: 当我将字符串添加到整数列表时,为什么编译器不引发编译器错误,或者运行时抛出运行时异常,例如*C

为什么可以将
字符串
插入以下代码中的
列表
?我有一个类将数字插入整数列表:

公共类主{
公共静态void main(字符串[]args){
列表=新的ArrayList();
增加(2);
增加(3);
增加(4);
插入器插入器=新插入器();
inserter.insertValue(列表);
系统输出打印(列表);
}
}
然后我有一个单独的类,它将一个
字符串插入到
列表中,数值字符串值为
“42”

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

[2, 3, 4, 42]

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

这可能是一个用于说明泛型的示例(我建议阅读该链接以充分理解这一点以及它在Java泛型中所起的关键作用)

  • 列表
    声明为
    列表
  • 当它作为参数传递给
    listValue
    时,它被强制转换为
  • 从这一点开始,在该方法中,运行时的程序不知道它最初是一个“整数列表”,因此它可以毫无例外地插入任何对象-在类声明中,类型变量被擦除为
    对象
  • 在main方法中,
    print
    命令只调用列表上的
    toString
    ,它不在乎它包含什么,因此它打印包含字符串的元素
  • 如果要查看异常,请尝试添加一行:

    Integer myInt = list.get(3); // try to get the string
    
    这将抛出一个
    ClassCastException
    ,因为编译器在擦除过程中会在必要时插入强制类型转换以保护类型安全

    †将参数化类型(如
    List
    )强制转换为原始类型(如
    List
    ),会给您一个编译器警告,告诉您此类问题可能即将发生。您可以使用(或
    “rawtypes”
    ,如果是)来抑制该警告。这是一种很好的“确认”您将要做的事情将导致未经检查的运行时异常的方式,同时也有助于告诉其他未来的编码人员可能会发生一些奇怪的事情。例如:

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

    编译器将抛出

    线程“main”java.lang.ClassCastException中的异常: 无法在处将java.lang.String转换为java.lang.Integer 234 Main.com.performance.Main.Main(Main.java:26)


    正如您在此处指定的类型
    ArrayList()和当您添加字符串时
    列表。添加(新字符串(“42”)

    您希望出现哪种编译器异常?代码从何处获得?我的猜测是,重点是解释如何在Java中传递参数,注意到传递给方法的是对列表的引用(通过值),而不是列表对象的副本。或者可能是为了展示原始类型。不过,还不完全清楚在哪里会出现错误。你能澄清一下这个问题吗?我想他对
    新字符串(“42”)的用法感到困惑
    可以插入到最初声明为
    List
    的值中。我希望是*CastException之类的东西,因为我尝试将字符串对象放入整数列表中。八月-是的,你是对的。我会将更改
    void insertValue(列表)
    添加到
    void insertValue(列表)中
    将产生错误并给出编译器exception@ZqBany. 我不确定这在这里是否相关,所以我将其略去。该示例的重点是说明原始类型以及它们如何规避类型安全性。将方法参数更改为参数化类型将破坏示例的对象。如果有人编写自己的泛型方法,希望他们永远不会使用原始类型。我只是认为这是java_用户所期望的行为,编译器应该在尝试将字符串添加到整数列表时抛出异常。添加这一小部分信息如何获得这种行为可能是有用的,然而,当然这将是不同的方法,对一些人来说,这可能是不可逆的。Elantit不清楚你在说什么。编译器不会抛出异常,运行时会抛出异常。同样根据OP的代码,在运行时不会抛出异常。你认为为什么会有这样的人?
    void insertValue(@SuppressWarnings("unchecked") List list)
    {
        list.add(new String("42"));
    }