2

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.

5
  • What is the error you get? Is it related to Caugth ClassCastException in my Java application Commented Feb 8, 2016 at 12:40
  • 1
    of course you can cast the elements in the returned array to their real type, but you cannot cast the array to T[] Commented Feb 8, 2016 at 12:40
  • 4
    Did you try something like RealType[] foo = (RealType[]) list.toArray()? Note that List<T> is a "generic" variant of List<Object>, but T[] is an entirely different class than Object[] (That's why there is a second toArray method) Commented Feb 8, 2016 at 12:41
  • Yes. I can get them out by element to element. So the reason i cannot cast the whole array to <T> is that the array's type Object is distinct from the elements type <T>? Commented Feb 8, 2016 at 12:56
  • We need a little bit of context code, like the snippet where you actually invoke toArray(). Commented Feb 8, 2016 at 12:59

5 Answers 5

3

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;
}
Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

0

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

Comments

0

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.

Comments

0

I think it has to do with the fact that arrays are covariant and thus you are allowed to cast from T[] to Object[], since Object can do anything T can, but the other way around does not make sense, Object can not do everything T can.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.