Java List toArray(T[] a) implementation

后端 未结 5 1334
挽巷
挽巷 2021-01-04 13:26

I was just looking at the method defined in the List interface:

Returns an array containing all of the elements in this list in the correct order; the

相关标签:
5条回答
  • 2021-01-04 13:28

    As mentioned by others, there are a couple different reasons:

    • You need to pass in the type somehow, and passing in an array of the specified type isn't an unreasonable way to do it. Admittedly, it might be nice if there was a version that you pass in the Class of the type you want too, for speed.
    • If you want to reuse your array, you can keep passing in the same one, rather than needing to create a new one each time. This can save time and memory, and GC issues if you need to do it many, many times
    0 讨论(0)
  • 2021-01-04 13:36
      357       public <T> T[] toArray(T[] a) {
      358           if (a.length < size)
      359               // Make a new array of a's runtime type, but my contents:
      360               return (T[]) Arrays.copyOf(elementData, size, a.getClass());
      361           System.arraycopy(elementData, 0, a, 0, size);
      362           if (a.length > size)
      363               a[size] = null;
      364           return a;
      365       }
    

    Maybe so it has a runtime type?

    From wiki:

    Consequently, instantiating a Java class of a parameterized type is impossible because instantiation requires a call to a constructor, which is unavailable if the type is unknown.

    0 讨论(0)
  • 2021-01-04 13:41

    My guess is that if you already know the concrete type of T at the point you're calling toArray(T[]), it's more performant to just declare an array of whatever it is than make the List implementation call Arrays.newInstance() for you -- plus in many cases you can re-use the array.

    But if it annoys you, it's easy enough to write a utility method:

    public static <E> E[] ToArray(Collection<E> c, Class<E> componentType) {
        E[] array = (E[]) Array.newInstance(componentType, c.size());
        return c.toArray(array);
    }
    

    (Note that there's no way to write <E> E[] ToArray(Collection<E> c), because there's no way to create an array of E at runtime without a Class object, and no way to get a Class object for E at runtime, because the generics have been erased.)

    0 讨论(0)
  • 2021-01-04 13:48

    Most likely this is to allow you to reuse arrays, so you basically avoid (relatively costly) array allocation for some use cases. Another much smaller benefit is that caller can instantiate array slightly more efficiently, since toArray() must use 'java.lang.reflect.Array.newInstance' method.

    0 讨论(0)
  • 2021-01-04 13:51

    This method is a holdover from pre-1.5 Java. Here is the link to javadoc

    Back then it was the only way to convert a list to a reifiable array.

    It is an obscure fact, but although you can store anything in the Object[] array, you cannot cast this array to more specific type, e.g.

    Object[] generic_array = { "string" };
    
    String[] strings_array = generic_array; // ClassCastException
    

    Seemingly more efficient List.toArray() does just that, it creates a generic Object array.

    Before Java generics, the only way to do a type-safe transfer was to have this cludge:

    String[] stronglyTypedArrayFromList ( List strings )
    {
        return (String[]) strings.toArray( new String[] );
        // or another variant
        // return (String[]) strings.toArray( new String[ strings.size( ) ] );
    }
    

    Thankfully generics made these kind of machinations obsolete. This method was left there to provide backward compatibility with pre 1.5 code.

    0 讨论(0)
提交回复
热议问题