public static void main(String[] args) {
List<Integer> integers = new ArrayList<>();
integers.add(5); //element #0
List list = integers;
list.add("foo"); //element #1
integers.get(1); //no error
System.out.println(integers.get(1)); //no error, prints "foo"
Integer i = integers.get(1); //throws ClassCastException
}
我试图理解转换类型变量的过程,声明为泛型类型参数,我有些困惑。因此,您可能会在我提供的示例中看到,在我们创建了一个非参数化的List
,它引用了与相同的对象List<Integer>
之后,我们可以将任何对象添加到该列表中(好的,在这里不足为奇),还有什么会引起混淆我是如此,我们可以从中提取非Integer
值List<Integer> integers
。为什么ClassCastException
在第一次或第二次呼叫时不抛出integers.get(1)
?
我假设返回参数类型的方法实际上总是返回,Object
并且那些返回的值在运行时隐式地尝试转换为l值类型或方法参数类型(因为在运行时没有泛型),但是以下测试使我确信:Integer
始终比Object
:
public static void main(String[] args) {
List<Integer> integers = new ArrayList<>();
integers.add(5); //element #0
List list = integers;
list.add("foo"); //element #1
print(integers.get(1));
}
private static void print(Object var) {
System.out.println(var);
}
//this method is entered
private static void print(Integer var) {
System.out.println(var);
}
private static void print(String var) {
System.out.println(var);
}
另一个有趣的事实是,尽管of ArrayList
的元素存储在Object[]
数组中,但在方法中返回之前,它们始终会转换为type参数中定义的类型get()
:
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
因此,如果有人可以将我指向逐步解释这些问题的文档,我将非常感谢
编译器在需要强制转换时插入强制转换。该方法System.out.println
的参数类型为Object
,因此不需要强制转换Integer
为。
对于这三种print
方法,将Integer
选择具有类型参数的方法,因此编译器将插入强制类型转换。根据复杂的规则集,在编译时选择使用三种方法中的哪一种。这些规则使用通用信息来查看integers.get(1)
具有type的信息Integer
,因此Integer
选择了版本并需要进行强制转换。结果,代码或多或少地等同于Java 4
代码
List integers = new ArrayList();
integers.add("foo");
integers.add(Integer.valueOf(5)); // No autoboxing in Java 4!
print((Integer) integers.get(1)); // Cast inserted by compiler
演员要(E)
在你的问题的最后一部分实际上并没有在运行时做任何事,所以不会抛出ClassCastException
。只需要使代码编译即可。您正在告诉编译器,是的,您确定Object
确实是一个E
并且以后不会引起异常(尽管您通过混合原始类型和泛型类型将其颠倒了)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句