简体   繁体   English

请从Java Generics FAQ解释此声明

[英]Please explain this statement from Java Generics FAQ

Can someone please explain what is meant by the following statement : 有人可以解释以下声明的含义:

Creation of arrays with a non-reifiable component type is not permitted. 不允许使用不可重新生成的组件类型创建数组。

This is written in Anjelika Langer's Java Generics FAQ 这是用Anjelika Langer的Java Generics FAQ编写

Creation of arrays with a non-reifiable component type is not permitted. 不允许使用不可重新生成的组件类型创建数组。

in practice means that generic array creation is illegal: 在实践中意味着通用数组创建是非法的:

new T[...] // prohibited

Generic arrays are not allowed, because arrays contain information about its component at runtime. 不允许使用通用数组,因为数组在运行时包含有关其组件的信息。 This is not true for generics. 对于泛型而言,情况并非如此。 Generics are implemented at compiler level. 泛型在编译器级别实现。 Hence, the component type must be known beforehand when the array is created. 因此,在创建数组时必须事先知道组件类型。

Java programming language does not permit the creation of arrays of parameterized types ie new T [] is not permitted Java编程语言不允许创建参数化类型的数组,即不允许使用新的T []

If the element type of an array were not reifiable (§4.7), the virtual machine could not perform the store check described in the preceding paragraph. 如果数组的元素类型不可恢复(第4.7节),则虚拟机无法执行前一段中描述的存储检查。 This is why creation of arrays of non-reifiable types is forbidden. 这就是为什么禁止创建不可再生类型的数组的原因。 One may declare variables of array types whose element type is not reifiable, but any attempt to assign them a value will give rise to an unchecked warning (§5.1.9). 可以声明其元素类型不可重新生成的数组类型的变量,但是任何为它们赋值的尝试都会产生未经检查的警告(第5.1.9节)。

You can read more about it here See more: 你可以在这里阅读更多相关信息了解更多:

Below is the code example which displays what can go wrong if you use varargs with generic types. 下面是代码示例,它显示了使用泛型类型的varargs时可能出现的问题。

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!"));
}

}

When the compiler encounters a varargs method, it translates the varargs formal parameter into an array. 当编译器遇到varargs方法时,它会将varargs形式参数转换为数组。 However, the Java programming language does not permit the creation of arrays of parameterized types . 但是, the Java programming language does not permit the creation of arrays of parameterized types In the method ArrayBuilder.addToList, the compiler translates the varargs formal parameter T... elements to the formal parameter T[] elements, an array. 在方法ArrayBuilder.addToList中,编译器将varargs形式参数T...元素转换为形式参数T[]元素,即数组。 However, because of type erasure, the compiler converts the varargs formal parameter to Object[] elements. 但是,由于类型擦除,编译器会将varargs形式参数转换为Object[]元素。 Consequently, there is a possibility of heap pollution. 因此,存在堆污染的可能性。

The following statement assigns the varargs formal parameter l to the Object array objectArgs: 以下语句将varargs形式参数l分配给Object数组objectArgs:

Object[] objectArray = l;

This statement can potentially introduce heap pollution. 这种说法可能会引入堆污染。 A value that does match the parameterized type of the varargs formal parameter l can be assigned to the variable objectArray, and thus can be assigned to l. 与varargs形式参数l的参数化类型匹配的值可以分配给变量objectArray,因此可以分配给l。 However, the compiler does not generate an unchecked warning at this statement. 但是,编译器不会在此语句中生成未经检查的警告。 The compiler has already generated a warning when it translated the varargs formal parameter List<String> ... l to the formal parameter List[] l. 编译器在将varargs形式参数List<String> ... l转换为形式参数List[] l时已生成警告。 This statement is valid; 本声明有效; the variable l has the type List[] , which is a subtype of Object[] . 变量l的类型为List[] ,它是Object[]的子类型。

Consequently, the compiler does not issue a warning or error if you assign a List object of any type to any array component of the objectArray array as shown by this statement: 因此,如果将任何类型的List对象分配给objectArray数组的任何数组组件,编译器不会发出警告或错误,如下所示:

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

This statement assigns to the first array component of the objectArray array with a List object that contains one object of type Integer. 此语句使用包含一个Integer类型的对象的List对象分配给objectArray数组的第一个数组组件。

Suppose you invoke ArrayBuilder.faultyMethod with the following statement: 假设您使用以下语句调用ArrayBuilder.faultyMethod:

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

At runtime, the JVM throws a ClassCastException at the following statement: 在运行时,JVM在以下语句中抛出ClassCastException:

   // ClassCastException thrown here
   String s = l[0].get(0);

Had you read further in that link, you would have found this statement: - 如果您在该链接中进一步阅读,您会发现此声明: -

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>

More from the JLS - Arrays : - 更多来自JLS - 阵列 : -

Discussion 讨论

If the element type of an array were not reifiable (§4.7), the virtual machine could not perform the store check described in the preceding paragraph. 如果数组的元素类型不可恢复(第4.7节),则虚拟机无法执行前一段中描述的存储检查。 This is why creation of arrays of non-reifiable types is forbidden. 这就是为什么禁止创建不可再生类型的数组的原因。 One may declare variables of array types whose element type is not reifiable, but any attempt to assign them a value will give rise to an unchecked warning (§5.1.9). 可以声明其元素类型不可重新生成的数组类型的变量,但是任何为它们赋值的尝试都会产生未经检查的警告(第5.1.9节)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM