我想知道为什么以下演员阵容未经检查:
==更新1 ==
我知道我们在运行时有类型擦除。请注意,输入参数为ArrayList
而非随机列表。ArrayList
实现List
和RandomAccess
。我知道此演员表不适用于LinkedList
或MySpecialArrayList
。但是这个方法的参数禁止这样做。我知道(在人们从List
移除RandomAccess
或ArrayList
之前,演员阵容不会在运行时失败,但为什么演员阵营未经检查?
==结束更新1 ==
private static <L extends List<GenericTokenType<?>> & RandomAccess> L castArrayList(ArrayList<GenericTokenType<?>> instance) {
return (L) instance;
}
我将此简化为[仍然警告]
private static <L extends List> L castArrayList(ArrayList instance) {
return (L) instance;
}
和[无警告]
private static List castArrayList(ArrayList instance) {
return (List) instance;
}
为什么这不起作用。 L
是List
(不是运行时类型,但编译器应该得到它。
重新解释这个问题:为什么它不适用于泛型参数返回类型?感谢
答案 0 :(得分:5)
在第一个和第二个示例中,您将ArrayList
转换为名为L
的类型。根据通用约束,L
还必须实现List
接口。因此,L
可能是ArrayList
,LinkedList
,Stack
或Vector
,也可能是您创建的实现List
的其他类。
到目前为止一切顺利,对吧?
现在让我们假设L
是ArrayList
表达式相当于:
(ArrayList) instance
显然这样可行。
但如果L
是LinkedList
怎么办?
(LinkedList) instance
这不起作用,因为你不能强制数组列表成为链表!它们是不同的数据结构!
为什么第三个工作呢?
在第三个示例中,您明确说明&#34;我希望此ArrayList
为List
&#34;。这是有效的,因为您投射instance
的类型是确定的。 ArrayList
实现List
,因此必须与之兼容!
方法将无法编译,因为
的子类LinkedList
是List
的子类型,如果没有强制转换,这不起作用....请解释一下,我只允许ArrayList
进入,而不是其他List
嗯,是的,你只允许ArrayList
传递给方法。但该方法的返回类型为L
。从通用约束中,我们知道L
可以是实现List
的任何类型。但是,您无法通过转换将ArrayList
转换为实现List
的任何类型。
答案 1 :(得分:4)
L
将被删除为List
,因为这是下限。但是,未经检查的原因是L
在技术上可以是List
的子类,但由于类型擦除,只能执行转换为(最多)List
。实际演员表将在具体类型可用时执行。
你也可以在字节码中很好地看到它:
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
7: invokestatic #4 // Method castArrayList:(Ljava/util/ArrayList;)Ljava/util/List;
// Cast is done here, after returning
10: checkcast #2 // class java/util/ArrayList
13: astore_1
14: return
public static <L extends java.util.List> L castArrayList(java.util.ArrayList);
Code:
0: aload_0
// No 'checkcast' here
1: areturn