Java 泛型总结(二):泛型与数组

  

Java 泛型总结(二):泛型与数组

在 Java 中,泛型和数组是两个不同的概念,但它们之间的关系比较微妙,需要仔细理解。本篇文章将讲解 Java 泛型和数组的关系,旨在帮助读者更深入理解 Java 泛型的本质。

泛型与数组的不同

  1. 泛型是编译期检查的,而数组是运行期检查的。这意味着,我们可以编写泛型代码来确保模板类型的安全性,一旦编译通过,就可以放心使用。而数组在运行期才会检查下标是否越界,如果越界会抛出 ArrayIndexOutOfBoundsException 异常。

  2. 泛型支持类型擦除,而数组不支持。类型擦除是指在编译期将泛型类型替换为它的边界类型或 Object 类型。但是由于历史原因,数组在编译期就已经确定了它的元素类型,因此无法擦除。

泛型数组的类型擦除

由于泛型支持类型擦除,因此我们无法直接创建泛型数组。例如,下面的代码会导致编译期错误:

List<Integer>[] arr = new List<Integer>[10];

这是因为在编译期,类型擦除会将 List<Integer> 替换为 List,因此实际上编译器会将上面的代码转换为:

List[] arr = new List[10];

这里的 List 是一个原始类型,它与 List<Integer> 不同。由于数组在创建时需要指定元素类型,因此会导致编译期错误。

如果你一定要创建泛型数组,可以使用以下方法:

List<Integer>[] arr = (List<Integer>[]) new List[10];

这里使用了强制类型转换,并且在创建数组时指定了 List 类型,因此可以通过编译。但是需要注意的是,由于类型擦除的存在,这个数组的元素类型实际上是 List,而不是 List<Integer>,因此需要进行强制类型转换才能使用。

数组类型转换的陷阱

在使用泛型时,我们经常需要将数组转换为 List 或者将 List 转换为数组。这时候就需要注意一些细节。

  1. 使用 Arrays.asList 将数组转换为 List 时,需要注意数组的类型。如果数组是原始类型,那么转换后的 List 中保存的就是数组的元素类型的包装类;如果数组是引用类型,那么转换后的 List 中保存的就是数组元素的引用。

``` java
int[] arr1 = {1, 2, 3};
List list1 = Arrays.asList(arr1); // 编译期错误

Integer[] arr2 = {1, 2, 3};
List list2 = Arrays.asList(arr2);

String[] arr3 = {"a", "b", "c"};
List list3 = Arrays.asList(arr3);
```

  1. 使用 List.toArrayList 转换为数组时,需要注意数组的类型。如果不指定元素类型,将返回一个 Object[] 数组。

``` java
List list4 = new ArrayList<>();
list4.add(1);
list4.add(2);
list4.add(3);

Object[] arr4 = list4.toArray();

Integer[] arr5 = list4.toArray(new Integer[0]);
```

总结

泛型和数组都是 Java 中比较重要的概念,它们之间的关系比较微妙。在使用泛型和数组时,需要认真思考它们的特性,并且避免一些常见的陷阱。希望通过本文的讲解,读者能够更加深入理解 Java 泛型的本质。

相关文章