List.toArray(T [])的奇数泛型行为

时间:2009-07-02 11:15:09

标签: java arrays list

我遇到了一些非常基本的东西,但今天非常令人困惑。我需要将列表转换为数组。该列表包含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> T[] toArray(T[] a)

这告诉我,我不应该施展。发生了什么事?

编辑:

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

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

它也有效。或List<Object>。所以它不必像建议的List<String>那样。我开始认为使用原始List类型也会改变该类中泛型方法的工作方式。

第二次编辑:

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

5 个答案:

答案 0 :(得分:29)

您忘记为列表指定类型参数:

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

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

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

没有任何演员。

答案 1 :(得分:3)

或做

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

仍然很奇怪

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

没有声明类型的

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

重点是将某些东西声明为通配符?不同于将其声明为Object。阅读有关通配符here

的更多信息