Java / Generics / Array问题

时间:2016-02-08 12:37:01

标签: java generics

我想最终理解泛型和数组之间的关系,所以我将基于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错误。

5 个答案:

答案 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所能做的一切。