我之前正在运行一些测试,但无法找到解释为什么这段代码能够完成它的工作:
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 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)
这个:
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)
现在应该不编译.
如果你写
... 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)
有用 :)