我想最终理解泛型和数组之间的关系,所以我将基于ArrayList<T>
提供一个对我来说不一致的例子:
Object[] elementData = new Object[size];
这是存储通用列表元素的地方。
public void add(T element){ elementData[size++] = element; }
public T get(int index) { return (T)elementData[index] }
完全有效。我可以获取基础<T>
对象,但是包含对这些对象的引用的数组是Object
。
与此相反:
public Object[] toArray()
{
Object[] result = new Object[size];
for(int i = 0;i<size;i++)
{
result[i] = elementData[i];
}
return result;
}
我无法将返回数组中的元素强制转换为它们的实际类型,但整个设置是相同的:Object
数组,其中包含对<T>
个对象的引用。我试图将元素转换为真实类型时出现ClassCastException
错误。
答案 0 :(得分:3)
如果查看Collection
界面,您会发现有两种toArray()
方法:
Object[] toArray()
返回一个包含此集合中所有元素的数组。
<T> T[] toArray(T[] a)
返回包含此集合中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。
原因是你不能创建通用数组,所以你只返回一个Object []。
制作toArray()
的通用方法很简单:
public <T> T[] toArray(T[] arr)
{
T[] result = arr.size == size ? arr : (T[])java.lang.reflect.Array
.newInstance(arr.getClass().getComponentType(), size);
for(int i = 0;i<size;i++)
{
result[i] = elementData[i];
}
return result;
}
答案 1 :(得分:1)
数组在运行时知道它们的组件类型。因此,要创建数组,需要在运行时提供组件类型。但是,在您的情况下,您在运行时不知道T
。因此,您无法创建真正属于T[]
的内容。您只能返回Object[]
,或依赖某人在运行时为您提供可以获得类型T
的内容。
答案 2 :(得分:0)
您可以将返回数组中的元素强制转换为实际类型。 但你无法将数组转换为T []
答案 3 :(得分:0)
java中的数组存在于java 5之前,它引入了泛型。 因此Arrays不依赖于泛型,这就是我们经常在API中使用Collections而不是数组的原因。 所以Collection最终可以被转换为Collection,但是Object []不能被转换为另一个数组T [],它将是另一个不兼容的类型。
答案 4 :(得分:0)
我认为这与数组是协变的事实有关,因此你可以从T[]
投射到Object[]
,因为Object
可以做任何事情T
可以,但反过来没有意义,Object
不能做T
所能做的一切。