请解释Java泛型常见问题解答中的这一陈述
有人能解释一下下面这句话的意思吗 不允许创建具有不可恢复组件类型的数组 允许 这是用英文写的 Java编程语言不允许创建参数化类型的数组,即不允许创建新的T[] 如果数组的元素类型不可重新定义(§4.7),则虚拟机无法执行上一段中描述的存储检查。这就是为什么禁止创建不可恢复类型的数组。可以声明其元素类型不可重定义的数组类型的变量,但任何为其赋值的尝试都将导致未经检查的警告(§5.1.9) 你可以阅读更多关于它的内容 请参阅更多:请解释Java泛型常见问题解答中的这一陈述,java,generics,Java,Generics,有人能解释一下下面这句话的意思吗 不允许创建具有不可恢复组件类型的数组 允许 这是用英文写的 Java编程语言不允许创建参数化类型的数组,即不允许创建新的T[] 如果数组的元素类型不可重新定义(§4.7),则虚拟机无法执行上一段中描述的存储检查。这就是为什么禁止创建不可恢复类型的数组。可以声明其元素类型不可重定义的数组类型的变量,但任何为其赋值的尝试都将导致未经检查的警告(§5.1.9) 你可以阅读更多关于它的内容 请参阅更多: 下面是一个代码示例,它显示了如果将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!"));
}
}
此语句可能会导致堆污染。可以将与varargs形式参数l的参数化类型匹配的值分配给变量objectArray,从而可以分配给l。但是,编译器不会在此语句中生成未检查的警告。编译器在翻译varargs形式参数List
时已生成警告。。。l到形式参数List[]
l。本声明有效;变量l的类型为列表[]
,它是对象[]
的子类型
因此,如果将任何类型的列表对象分配给objectArray数组的任何数组组件,则编译器不会发出警告或错误,如下语句所示:
objectArray[0] = Arrays.asList(42);
ArrayBuilder.faultyMethod(Arrays.asList("Hello!"), Arrays.asList("World!"));
// ClassCastException thrown here
String s = l[0].get(0);
此语句将包含一个整型对象的列表对象分配给objectArray数组的第一个数组组件
假设使用以下语句调用ArrayBuilder.faultyMethod:
objectArray[0] = Arrays.asList(42);
ArrayBuilder.faultyMethod(Arrays.asList("Hello!"), Arrays.asList("World!"));
// ClassCastException thrown here
String s = l[0].get(0);
在运行时,JVM在以下语句中抛出ClassCastException:
objectArray[0] = Arrays.asList(42);
ArrayBuilder.faultyMethod(Arrays.asList("Hello!"), Arrays.asList("World!"));
// ClassCastException thrown here
String s = l[0].get(0);
如果您进一步阅读该链接,您会发现以下声明:-
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>
Pair不是可重新定义的类型,也就是说,它作为一个
类型擦除的结果,并在运行时表示为原始类型对
而不是确切的类型对
更多信息来自:-
讨论
如果数组的元素类型不可重新定义(§4.7),则虚拟
计算机无法执行前面描述的存储检查
段落这就是为什么创建不可恢复类型的数组非常困难的原因
被禁止的可以声明数组类型的变量,其元素
类型不可重新定义,但任何为其赋值的尝试都将失败
引起未经检查的警告(§5.1.9)
不允许创建具有不可恢复组件类型的数组
实际上,泛型数组创建是非法的:
new T[...] // prohibited
不允许使用泛型数组,因为数组在运行时包含有关其组件的信息。对于泛型,情况并非如此。泛型是在编译器级别实现的。因此,在创建数组时,必须事先知道组件类型。相关:这是一个很好的读法。@Keyser请提供link@Geek我做了(更新),但说真的,这是维基百科:你能解释一下为什么你的答案中不允许这样做吗?这只会使它更完整。我已经添加了一个解释,让我明白。对于更深入的讨论,问题的答案很有用。faultyMethod()的签名或方法的调用没有问题。错误在方法体内部,但与泛型数组创建无关。因为调用这个vararg方法需要创建一个泛型数组,这是语言规范中的一个漏洞。我们可以将它用作合法创建泛型数组的后门@不可改变的是。我不知道你为什么没有在那个帖子上得到选票:)。