转换为Generic类型java(为什么未选中)

时间:2016-12-01 08:05:59

标签: java generics

我想知道为什么以下演员阵容未经检查:

==更新1 ==

我知道我们在运行时有类型擦除。请注意,输入参数为ArrayList而非随机列表。ArrayList实现ListRandomAccess。我知道此演员表不适用于LinkedListMySpecialArrayList。但是这个方法的参数禁止这样做。我知道(在人们从List移除RandomAccessArrayList之前,演员阵容不会在运行时失败,但为什么演员阵营未经检查?

==结束更新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;
}

为什么这不起作用。 LList(不是运行时类型,但编译器应该得到它。

重新解释这个问题:为什么它不适用于泛型参数返回类型?感谢

2 个答案:

答案 0 :(得分:5)

在第一个和第二个示例中,您将ArrayList转换为名为L的类型。根据通用约束,L还必须实现List接口。因此,L可能是ArrayListLinkedListStackVector,也可能是您创建的实现List的其他类。

到目前为止一切顺利,对吧?

现在让我们假设LArrayList表达式相当于:

(ArrayList) instance

显然这样可行。

但如果LLinkedList怎么办?

(LinkedList) instance

这不起作用,因为你不能强制数组列表成为链表!它们是不同的数据结构!

为什么第三个工作呢?

在第三个示例中,您明确说明&#34;我希望此ArrayListList&#34;。这是有效的,因为您投射instance的类型是确定的。 ArrayList实现List,因此必须与之兼容!

  

方法将无法编译,因为LinkedListList的子类型,如果没有强制转换,这不起作用....请解释一下,我只允许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