在Collection
课程中有两种toArray()
方法:<T> T[] toArray(T[] a)
和Object[] toArray()
。没有E[] toArray()
方法。为什么?
它与类型擦除有关,但有方法 - boolean add(E e)
。为什么可以创建参数化add
并且无法创建toArray()
方法?
答案 0 :(得分:11)
没有E [] toArray()方法。为什么?
在执行时实际创建E[]
是不可能的,因为它不会因为类型擦除而知道要创建的数组的类型
add
方法确实接受任何内容,但编译器只是先检查参数类型是否与E
兼容。在执行时不需要知道任何事情。同样,对于类似List.get
的内容,编译器会在调用代码中插入强制转换:
List<String> strings = new ArrayList<>();
strings.add("hello");
String first = strings.get(0);
编译为与此pre-generics代码相同的代码:
List strings = new ArrayList();
strings.add("hello");
String first = (String) strings.get(0);
现在这很好,因为我们在调用代码的执行时知道String
类型...但是在toArray()
中,创建数组的代码需要知道类型...和类型擦除意味着它实际上并不知道。传递给toArray()
的数组允许它创建相同类型的数组。实际上,创建的对象的实际类型可以显示为依赖于您传入的数组:
import java.util.*;
public class Test {
public static void main(String[] args) {
List<Object> objects = new ArrayList<Object>();
objects.add("xyz");
Object[] array1 = objects.toArray(new String[0]);
Object[] array2 = objects.toArray(new Object[0]);
System.out.println(array1.getClass()); // class [Ljava.lang.String;
System.out.println(array2.getClass()); // class [Ljava.lang.Object;
}
}
如果我们传入new Integer[0]
,则会编译,但是当ClassCastException
尝试时我们已经获得了toArray
将String
(唯一元素)转换为Integer
。