10

有人可以解释以下语句的含义:

不允许创建具有不可具体化组件类型的数组。

这是在Anjelika Langer 的 Java 泛型常见问题解答中编写的

4

3 回答 3

9

不允许创建具有不可具体化组件类型的数组。

实际上意味着创建通用数组是非法的:

new T[...] // prohibited

不允许使用通用数组,因为数组在运行时包含有关其组件的信息。这不适用于泛型。泛型在编译器级别实现。因此,在创建数组时必须事先知道组件类型。

于 2012-10-09T13:06:03.160 回答
4

Java 编程语言不允许创建参数化类型的数组,即不允许创建 new T []

如果数组的元素类型不可具体化(第 4.7 节),则虚拟机无法执行上一段中描述的存储检查。这就是为什么禁止创建不可具体化类型的数组的原因。可以声明其元素类型不可具体化的数组类型的变量,但任何试图为它们赋值的尝试都会引发未经检查的警告(第 5.1.9 节)。

你可以在这里阅读更多关于它的信息 查看更多:

下面是代码示例,它显示了如果您将可变参数与泛型类型一起使用会出现什么问题。

public class ArrayBuilder {

public static <T> void addToList(List<T> listArg, T... elements) {
    for (T x : elements) {
        listArg.add(x);
    }
}

public static void faultyMethod(List<String>... l) {
    Object[] objectArray = l; // Valid
    objectArray[0] = Arrays.asList(42);
    String s = l[0].get(0); // ClassCastException thrown here
}

public static void main(String[] args) {

    List<String> stringListA = new ArrayList<String>();
    List<String> stringListB = new ArrayList<String>();

    ArrayBuilder.addToList(stringListA, "Seven", "Eight", "Nine");
    ArrayBuilder.addToList(stringListA, "Ten", "Eleven", "Twelve");
    List<List<String>> listOfStringLists = new ArrayList<List<String>>();
    ArrayBuilder.addToList(listOfStringLists, stringListA, stringListB);

    ArrayBuilder.faultyMethod(Arrays.asList("Hello!"),
            Arrays.asList("World!"));
}

}

当编译器遇到可变参数方法时,它会将可变参数形式参数转换为数组。然而,the Java programming language does not permit the creation of arrays of parameterized types. 在方法 ArrayBuilder.addToList 中,编译器将 varargs 形参T...元素转换为形参T[]元素,一个数组。但是,由于类型擦除,编译器将varargs形式参数转换为Object[]元素。因此,存在堆污染的可能性。

以下语句将可变参数形式参数分配给lObject 数组 objectArgs:

Object[] objectArray = l;

此语句可能会引入堆污染。与可变参数形式参数 l 的参数化类型匹配的值可以分配给变量 objectArray,因此可以分配给 l。但是,编译器不会在此语句处生成未经检查的警告。List<String>编译器在将可变参数形式参数... l 转换为形式参数l时已经生成警告List[]。本声明有效;变量 l 的类型List[]是 ,它是 的子类型Object[]

因此,如果将任何类型的 List 对象分配给 objectArray 数组的任何数组组件,编译器不会发出警告或错误,如以下语句所示:

objectArray[0] = Arrays.asList(42);

此语句将包含一个 Integer 类型对象的 List 对象分配给 objectArray 数组的第一个数组组件。

假设您使用以下语句调用 ArrayBuilder.faultyMethod:

   ArrayBuilder.faultyMethod(Arrays.asList("Hello!"), Arrays.asList("World!"));

在运行时,JVM 在以下语句中抛出 ClassCastException:

   // ClassCastException thrown here
   String s = l[0].get(0);
于 2012-10-09T13:02:52.067 回答
3

如果您在该链接中进一步阅读,您会发现以下声明:-

Pair<String,String> is not a reifiable type, that is, it loses information as a 
result of type erasure and is at runtime represented as the raw type Pair 
instead of the exact type Pair<String,String>

更多来自JLS - 阵列:-

讨论

如果数组的元素类型不可具体化(第 4.7 节),则虚拟机无法执行上一段中描述的存储检查。这就是为什么禁止创建不可具体化类型的数组的原因。可以声明其元素类型不可具体化的数组类型的变量,但任何试图为它们赋值的尝试都会引发未经检查的警告(第 5.1.9 节)。

于 2012-10-09T13:03:18.037 回答