有两个程序 为什么第一个代码有效?我希望它在访问元素时抛出运行时异常,因为添加了字符串而不是整数
同样.. 第二个代码在访问元素时抛出运行时异常,尽管它能够轻松地在 arrayList 中添加 Integer,尽管声明它保存 String。
在这两段代码中,我们都成功添加了不同的数据类型,但是在访问元素时似乎出现了问题
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
Test.addToList(arrayList);
System.out.println(arrayList.get(0));
}
public static void addToList(ArrayList arrayList) {
arrayList.add("i");
}
}
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
Test.addToList(arrayList);
System.out.println(arrayList.get(0));
}
public static void addToList(ArrayList arrayList) {
arrayList.add(1);
}
}
最佳答案
由于type erasure,您可以在这两种情况下添加元素。在运行时,该类不知道它被声明为 new ArrayList<String>()
,只是它被声明为 new ArrayList()
.
在 println
在这种情况下,该方法的编译时重载决策就会发挥作用。 System.out
是 PrintStream ,其中有几个重载 println
。其中包括:
...
void println(Object x);
void println(String x);
Java 编译器将选择其中最具体的一个。在 ArrayList<Integer>
情况是第一个,在 ArrayList<String>
中情况是第二种。一旦完成此操作,作为类型删除处理的一部分,它将强制转换原始 ArrayList::get(int)
的对象结果。调用所需的类型,但前提是需要进行强制转换。
以ArrayList<Integer>
为例调用时,强制转换是不必要的( ArrayList::get(int)
返回一个对象,这正是该方法所期望的),因此 javac 省略了它。以ArrayList<String>
为例call,它是必需的,所以javac添加了它。您所看到的:
System.out.println(arrayList.get(0));
实际上编译为:
System.out.println((String) arrayList.get(0));
但是该元素不是字符串,这就是导致 ClassCastException 的原因。
关于java - 运行时的泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41439041/