Java泛型 - 允许混合类型?

ass*_*ias 3 java generics

我之前正在运行一些测试,但无法找到解释为什么这段代码能够完成它的工作:

public class Test {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList(Arrays.asList(Double.valueOf(0.1234)));
        System.out.println(list.get(0)); //prints 0.1234
        Object d = list.get(0);
        System.out.println(d.getClass()); // prints class java.lang.Double
        System.out.println(list.get(0).getClass()); // ClassCastException
    }
}
Run Code Online (Sandbox Code Playgroud)

这引出了一些问题:

  • 为什么List <Integer>首先接受一个Double(它应该编译完毕)?
  • 为什么第二次打印工作而不是第三次打印,虽然看起来他们正在做同样的事情?

编辑
我理解以下两个陈述:

List aList = new ArrayList(); //I can add any objects in there
List<Integer> aList = new ArrayList<Integer>(); //I can only add something that extends Integer in there
Run Code Online (Sandbox Code Playgroud)

但是我不明白为什么这个被授权以及为什么它在运行时实际上有效,尽管有些操作会产生ClassCastException - 我希望在上面发布的代码的第一行有一个ClassCastException:

List<Integer> aList = new ArrayList(); //I can any objects in there
Run Code Online (Sandbox Code Playgroud)

Oli*_*rth 6

这个:

new ArrayList(Arrays.asList(Double.valueOf(0.1234)))
Run Code Online (Sandbox Code Playgroud)

创建一个原始(无类型)ArrayList,在其中可以放置任何东西.这是正确的方法:

new ArrayList<Integer>(Arrays.asList(Double.valueOf(0.1234)))
Run Code Online (Sandbox Code Playgroud)

现在应该不编译.

  • 还应该注意的是,编译原始程序会在"list"被赋值的行上产生关于未经检查的调用的警告.基本上,如果你使用泛型,你的代码保证不会抛出`ClassCastException`**只有当所有内容都编译时没有任何关于未经检查的强制转换的警告**. (3认同)

Ang*_*chs 5

如果你写

... new ArrayList<Integer>(...
Run Code Online (Sandbox Code Playgroud)

相反,它会导致编译器异常.

关于它的工作原理:

System.out.println(list.get(0)); //prints 0.1234
Run Code Online (Sandbox Code Playgroud)

该方法Object.toString()Double和中是相同的Integer(并且因为System.out.println()期望一个Object不会被强制转换为Integer(编译器优化了抛出))

Object d = list.get(0);
System.out.println(d.getClass()); // prints class java.lang.Double
Run Code Online (Sandbox Code Playgroud)

同样如此.getClass().在这里,优化器再次放弃了演员.

System.out.println(list.get(0).getClass()); // ClassCastException
Run Code Online (Sandbox Code Playgroud)

这实际上是Integer从列表中创建的,但是失败了.它执行转换,因为优化器认为它需要这样做,因为它不是显而易见的,它不需要.

如果您将最后一行更改为:

    System.out.println(((Object)list.get(0)).getClass());
Run Code Online (Sandbox Code Playgroud)

有用 :)