假设您有一个arraylist定义如下:
ArrayList<String> someData = new ArrayList<>();
稍后在代码中,由于泛型,您可以这样说:
String someLine = someData.get(0);
而且编译器完全知道它将得到一个字符串。是的仿制药!但是,这将失败:
String[] arrayOfData = someData.toArray();
toArray()将始终返回对象数组,而不是已定义的泛型数组。为什么该get(x)方法知道返回的内容,但toArray()默认为Objects?
toArray()
get(x)
如果你看一下执行toArray(T[] a)的的ArrayList 类,它是这样的:
toArray(T[] a)
public <T> T[] toArray(T[] a) { if (a.length < size) // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; }
这种方法的问题是您需要传递相同泛型的数组。现在考虑如果此方法不带任何参数,则实现将类似于以下内容:
public <T> T[] toArray() { T[] t = new T[size]; // compilation error return Arrays.copyOf(elementData, size, t.getClass()); }
但是这里的问题是, 您不能在Java中创建通用数组, 因为编译器不知道确切T代表什么。换句话说 , 在Java中不允许 创建非可校正类型的数组 (JLS§4.7)。
T
数组存储异常 (JLS§10.5)中的另一个重要报价:
如果数组的组件类型不可修改(第4.7节),则Java虚拟机将无法执行上一段所述的存储检查。 这就是为什么禁止使用不可修改元素类型的数组创建表达式的原因(第15.10.1节)。
这就是Java提供重载版本的原因toArray(T[] a)。
我将重写toArray()方法以告诉它它将返回E数组。
因此toArray(),您应该使用而不是覆盖toArray(T[] a)。
无法从Java Doc 创建类型参数的实例可能对您也很有趣。