gpt4 book ai didi

java - 使用原始类型数组初始化的通配符集合数组

转载 作者:行者123 更新时间:2023-12-04 04:57:00 27 4
gpt4 key购买 nike

很合理,编译器会为此提供原始类型转换警告:

//1
List<?> arrList = new ArrayList(); //raw type warning

但是,编译器可以使用此行(没有警告):
//2
List<?>[] arr_of_arrList = new ArrayList[3];// no warning, why ?

所以,没有编译器的任何提示,我可以进一步做:
 arr_of_arrList[0] = new ArrayList<String>();
arr_of_arrList[1] = new ArrayList<Integer>();

您能否解释为什么给定的数组初始化(2)被认为是类型安全的,而不是第一次列表初始化(1),以及编译器在情况 2 中正在做什么。

最佳答案

编译器还会在定义时警告您:

List<String>[] foo = new ArrayList[3];

这是因为通过它的警告,编译器试图让您知道存储在 List<String>[] foo 中的列表。可能不是泛型类型 String .你总是可以得到一个 List<Integer>foo在运行时:
 void main(){

List<String>[] array = new List[1];
fill(array);

// The compiler could not check the array at compile time, so
// the next line is permitted. But you just created yourself a time bomb.
List<String> list = array[0];

// The next line will finally cause a ClassCastException at runtime!
// Good luck with debugging, especially if you have passed your list
// arround for a while.
// If you had defined List<?>[] foo, this assignment would have been
// forbidden without explicit casting to String. But at least the "type"
// of the array did not make you false promises about the generic type
// of the list.
String value = list.get(0);
}

// This method receives an array of lists. At runtime the generic type of
// the array is gone. Therefore, a call to this method can be called with
// anz List<SomeType>[] array as an argument.
void fill(List<?>[] array) {
List<Integer> list = new ArrayList<Integer>();
list.add(123)
array[0] = list;
}

在 Java 中, 泛型数组没有泛型表示 .相反,所有类型为 List[] 的数组(在字节码中,该类型被称为 [java.util.List )共享一个单一的表示形式,即 List<String>List<Integer>或其他任何东西。这是出于向后兼容性的原因以及数组在 Java 字节码中的表示方式。换句话说,编译器没有办法标记一个数组 实例仅接受例如 List<String>对象。相反,编译器只能将数组标记为接受 List 的子类型。就像在 Java 5 之前一样。

通过说明
List<?>[] foo = new ArrayList[3];

您基本上告诉编译器您知道编译器无法检查除此之外的任何内容 List foo 表示的数组中的 s属于 Object 的某些亚型什么当然是微不足道的。 ( ? 等价于 ? extends Object 。)或者换句话说,当使用通配符 ? 时,您要求编译器确保 List包含在 foo 中是 任何 泛型。如前所述,因为这个需求是微不足道的,编译器实际上可以释放这个需求并且不会产生警告。

现在问题来了:
class MyClass<T extends Number> { }

你仍然不能说:
MyClass<? extends Number>[] foo = new MyClass[3];

没有编译器警告。为什么?我不知道。它应该是类型最安全的声明。当看到同义声明时,这更没有意义
MyClass<?>[] foo = new MyClass[3];

被接受。出于这个原因,我假设编译器只是在完全涉及数组时跳过泛型类型变量的类型检查,但通过确保用户键入 <?> 来确保您认识到检查数组的泛型类型是不可能的。与完全缺乏泛型类型的遗留代码相比。

关于java - 使用原始类型数组初始化的通配符集合数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16633053/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com