List.toArray(T )的奇数generics行为

我遇到了一些非常基本但今天非常困惑的事情。 我需要将列表转换为数组。 该列表包含String实例。 使用List.toArray(T[])完美示例,因为我想要一个String[]实例。 但是,如果没有将结果显式地转换为String[] ,它将无法工作。

作为测试场景,我使用了以下代码:

 import java.util.Arrays; import java.util.List; public class MainClass { public static void main(String args[]) { List l = Arrays.asList("a", "b", "c"); String stuff[] = l.toArray(new String[0]); System.err.println(Arrays.asList(stuff)); } } 

哪个不编译。 它几乎是javadoc中示例的精确副本,但编译器说明如下:

 MainClass.java:7: incompatible types found : java.lang.Object[] required: java.lang.String[] String stuff[] = l.toArray(new String[0]); ^ 

如果我向String[]添加一个强制转换,它将编译并完美运行。 但是当我查看toArray方法的签名时,这不是我所期望的:

  T[] toArray(T[] a) 

这告诉我,我不应该投。 到底是怎么回事?

编辑:

奇怪的是,如果我将列表声明更改为:

 List l = Arrays.asList("a", "b", "c"); 

它也有效。 或者List 。 因此它不必像建议的那样是List 。 我开始认为使用原始List类型也会改变该类中generics方法的工作方式。

第二次编辑:

我想我现在明白了。 Tom Hawtin在下面的评论中所写的内容似乎是最好的解释。 如果以原始方式使用generics类型,则编译器将擦除该实例中的所有generics信息。

您忘了为List指定type参数:

 List l = Arrays.asList("a", "b", "c"); 

在这种情况下,你可以写安全:

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

没有任何演员。

或者做

 List l = Arrays.asList("a", "b", "c"); 

还是很奇怪

 List l = Arrays.asList("a", "b", "c"); 

这将使它编译,您使用generics来说“这是一个字符串列表”,因此toArray方法知道要返回哪种类型的数组。

那是因为你的列表包含对象,而不是字符串。 如果您将列表声明为List ,编译器会很高兴。

没有声明类型的List将默认为“对象List ”,而List表示“未知列表”。 在generics类型的世界中,“对象列表”与“字符串列表”不同,但编译器不能对“未知列表”说同样的事实。 如果您已将其声明为未知,那么就编译器而言,这没关系。

重点是将某些东西称为通配符? 不同于将其声明为Object。 在这里阅读有关通配符的更多信息