fro*_*SPb 22 java generics raw-types parameterized-types
这是一段代码片段:
import java.util.*;
class Test
{
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>();
addToList(list);
Integer i = list.get(0); //#1 fails at run-time
String s = list.get(0); //#2 fails at compile-time
list.get(0); //#3 works fine
System.out.println(list.get(0)); //#4 works fine, prints "string"
}
static void addToList(List list){
list.add("string");
}
}
Run Code Online (Sandbox Code Playgroud)
我理解为什么可以在参数化列表中插入String类的对象.
似乎我理解为什么代码标记#1和#2失败.
但是,为什么#3和#4工作?据我所知,编译器在类型擦除后添加了适当的强制转换,因此当我调用时list.get(0),此方法应该返回一个先前转换为Integer的Object.那么为什么在运行时没有ClassCastException出现在#3和#4?
das*_*ght 23
#3有效,因为返回的对象get(int)被忽略.0返回存储在位置的任何内容,但由于没有强制转换,因此不会发生错误.
#4工作正常的原因相同:生成的对象get(0)被视为java.lang.Object子类in println,因为toString被调用.由于toString()可用于所有Java对象,因此调用完成且没有错误.
首先,你可以添加一个字符串的原因List<Integer>.在方法中
static void addToList(List list){
Run Code Online (Sandbox Code Playgroud)
你使用原始类型.原始类型纯粹是为了与较旧的Java版本兼容而存在,不应在新代码中使用.在该addToList方法中,Java编译器不知道list应该只包含整数,因此在向其添加String时它不会抱怨.
至于你两个陈述的不同行为.Integer i = list.get(0)在编译时不会失败,因为Java认为list只包含Integers.只有在运行时才会发现第一个元素list不是Integer,因此你得到了一个ClassCastException.
String s = list.get(0)在编译时失败,因为Java编译器假定list只包含整数,因此它假定您尝试将一个Integer分配给String引用.
只是list.get(0)不存储方法调用的结果.因此,无论是在编译时还是在运行时都没有任何失败的原因.
最后,System.out.println(list.get(0))work是因为System.out是a PrintStream并且有一个println(Object)方法,可以用Integer参数调用.
如果你看ArrayList#get方法.就是这个:
public E get(int index) {
//body
}
Run Code Online (Sandbox Code Playgroud)
但在运行时它实际上是:
public Object get(int index) {
//body
}
Run Code Online (Sandbox Code Playgroud)
所以当你这样做时Integer i = list.get(0);
编译器将它转换为:
Integer i = (Integer)list.get(0);
Run Code Online (Sandbox Code Playgroud)
现在在运行时,list.get(0)返回一个Object类型(实际上是String).它现在尝试转换String => Integer,但它失败了.
3
因为它只是:
list.get(0)
Run Code Online (Sandbox Code Playgroud)
编译器确实为任何事物添加了类型转换.所以它只是,list.get(0).
4
System.out.println(list.get(0));
Run Code Online (Sandbox Code Playgroud)
list.get(0)返回一个Object类型.因此public void println(Object x)调用PrintStream的方法.
记住println(Object x)被调用而不是println(String x).