被Java泛型混淆需要强制转换

我对以下代码感到困惑:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class GenericsTest<T extends List> {

  public void foo() {
    T var = (T) new LinkedList();
  }

  public static void main(String[] args) {
      GenericsTest<ArrayList> gt1 = new GenericsTest<ArrayList>();
      gt1.foo();
      System.out.println("Done");
  }
}

无论我传递给构造函数的Type参数是什么,T的运行时类型似乎都是java.util.List.

那么为什么编译器在分配var时需要转换为T?它不应该在编译时知道LinkedList可以分配给List吗?

我理解代码是假的,我理解为什么它在运行时工作,即使它看起来不应该.令我困惑的部分是为什么编译器要求我在进行赋值时键入(T)?然而,如果没有伪造的话,它可以很好地编译.

据推测,编译器理解擦除.看起来编译器应该能够在没有强制转换的情况下编译代码.

解决方法

海报在评论中问道,

However,presumably the compiler knows
that so why does it need to have the
cast to (T). Is there any possible way
the cast could ever fail?

这个演员阵容不会失败.但编译器警告说,这段代码会设置一个时间炸弹,以便在ClassCastException的其他地方爆炸.

在该示例中,没有理由使用泛型,因为API都没有使用类型变量T.请查看更真实的泛型应用程序.

public class GenericsTest<T extends List> {

 3   public T foo() {
 4     T var = (T) new LinkedList();
 5     return var;
 6   }

 8   public static void main(String... argv) {
 9     GenericsTest<ArrayList> gt1 = new GenericsTest<ArrayList>();
10     gt1.foo();
11     System.out.println("Test one okay");
12     ArrayList<?> list = gt1.foo();
13     System.out.println("Test two okay");
14   }

   }

在第12行抛出ClassCastException .ClassCastException,没有强制转换?调用代码完全正确.无效的强制转换(bug)位于调用方法的第4行.但是这个例外是在某个时间和地点提出的.

Java泛型的目的是确保代码是类型安全的.如果所有代码都是在没有“未选中”警告的情况下编译的,那么保证在运行时不会引发ClassCastException.但是,如果您所依赖的库写得不正确,就像这个例子一样,承诺就会被破坏.

相关文章

摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠...
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠...
今天犯了个错:“接口变动,伤筋动骨,除非你确定只有你一个...
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:...
本文目录 线程与多线程 线程的运行与创建 线程的状态 1 线程...