我遇到了一些非常基本的东西,但今天非常令人困惑。我需要将列表转换为数组。该列表包含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在下面的评论中所写的内容似乎是最好的解释。如果以原始方式使用泛型类型,则编译器将擦除该实例中的所有泛型信息。
答案 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
的更多信息