简体   繁体   中英

Java / Generics / Array problems

I would like to understand the relationship between generics and arrays finally, so i will provide an example which is inconsisent for me, based on an ArrayList<T> :

Object[] elementData = new Object[size];

This is where elements of the generic list are stored.

public void add(T element){ elementData[size++] = element; }

public T get(int index) { return (T)elementData[index] }

Completely works. I can get out the underlying <T> objects, however the array which contains the references to these objects is Object .

In contrast to this:

public Object[] toArray()
{       
    Object[] result = new Object[size];

    for(int i = 0;i<size;i++)
    {
        result[i] = elementData[i];
    }

    return result;
}

I cannot cast the elements in the returned array to their real type, however the whole set up is the same: an Object array which contains references to <T> objects. I got ClassCastException error, when trying to cast the elements to their real type.

If you look into the Collection interface, you see that there are 2 toArray() methods:

  • Object[] toArray()

    Returns an array containing all of the elements in this collection.

  • <T> T[] toArray(T[] a)

    Returns an array containing all of the elements in this collection; the runtime type of the returned array is that of the specified array.

The reason for that is that you cannot make generic arrays, so you only return a Object[].

Making a generic method of your toArray() is simple:

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;
}

Arrays know their component type at runtime. Therefore, to create an array, you need to provide the component type at runtime. However, in your case you don't know T at runtime. Therefore, you cannot create something that is truly a T[] . You can only return Object[] , or rely on someone giving you something with which you can get the type T from at runtime.

You can cast the elements in the returned array to their real type. But you cannot cast the array to T[ ]

Arrays in java existed before java 5, which introduces Generics. So Arrays doesn't rely on generics, this is why we often use Collections instead of arrays in API. So Collection can eventually be casted to Collection, but Object[] cannot be casted to another array T[], it would be another incompatible type.

我认为这与以下事实有关:数组是协变的,因此您可以从T[] Object[]Object[] ,因为Object可以完成T可以做的任何事情,但是反之则没有意义, Object不能尽一切T即可。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM