组合原始类型和泛型方法

2022-09-01 14:12:18

这里有一个问题,第一个代码清单编译得很好(JDK 1.6 |JDK 1.7):

ArrayList<String> a = new ArrayList<String>();
String[] s = a.toArray(new String[0]);

但是,如果我将引用声明为原始类型:List

ArrayList a = new ArrayList();
String[] s = a.toArray(new String[0]);

我收到一个编译器错误,说是必需的,但被发现了。String[]Object[]

这意味着我的编译器正在将泛型方法解释为返回,尽管接收了 a 作为其参数。Object[]String[]

我仔细检查了方法签名:toArray(myArray)

<T> T[] toArray(T[] a);

因此,它是一个参数化的方法,其类型参数与 List 的类型参数没有任何关系(即 )。<T><E>

我不知道在这里使用原始类型如何影响使用独立类型参数的参数化方法的评估。

  • 有没有人知道为什么这段代码不能编译?
  • 有没有人知道任何记录此行为的参考?

答案 1

这并不完全是你所期望的,但是如果你以原始形式引用泛型类,你就会失去以任何方式使用泛型作为实例成员的能力。它也不仅限于泛型方法,请查看以下内容:

 public class MyContainer<T> {

     public List<String> strings() {
         return Arrays.asList("a", "b");
     }
 }

 MyContainer container = new MyContainer<Integer>();
 List<String> strings = container.strings(); //gives unchecked warning!

这是 JLS (4.8) 的相关部分:

未从其超类或超接口继承的原始类型 C 的构造函数 (§8.8)、实例方法 (§8.4、 §9.4) 或非静态字段 (§8.3) M 是原始类型,该类型对应于在对应于 C 的泛型声明中擦除其类型。


答案 2

当你不使用泛型时,编译器会将其视为原始类型,因此每个泛型类型都变得,因此您无法通过,因为它需要
所以这是交易 - 如果你使用ObjectString[]Object[]

List l = new ArrayList<String>();

您正在使用原始类型,并且其所有实例成员都将替换为其纠删对应项。特别是,实例方法声明中出现的每个参数化类型都将替换为其原始对应项。有关详细信息,请参阅 JLS 4.8。


推荐