United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-7023484 : java.util.Collection#toArray(T[]) is not typesafe -- suggesting helper method

Details
Type:
Enhancement
Submit Date:
2011-03-01
Status:
Open
Updated Date:
2012-11-19
Project Name:
JDK
Resolved Date:
Component:
core-libs
OS:
windows_7
Sub-Component:
java.util:collections
CPU:
x86
Priority:
P4
Resolution:
Unresolved
Affected Versions:
6u24
Targeted Versions:

Related Reports

Sub Tasks

Description
A DESCRIPTION OF THE REQUEST :
java.util.Collection defines method <T> T[] toArray(T[] a);

Unfortunately, this is not compile-time type-safe, which can be seen in the test case below. The problem is that the signature of the method doesn't refer to the type parameter <E> of Collection.

The correct signature of toArray(..) would be something like this, but this is not valid in Java: <T super E> T[] toArray(T[] a);

Since I don't think Collection#toArray(T[]) can be fixed, I suggest a type-safe helper method in the java.util.Collections class:

	/**
	 * Returns an array containing all of the elements in the given collection. This is a
	 * compile-time type-safe alternative to {@link Collection#toArray(Object[])}.
	 *
	 * @param collection the source collection
	 * @param clazz the type of the array elements
	 * @param <A> the type of the array elements
	 * @return an array of type <code>A</code> containing all of the elements in the given
	 *         collection
	 * @throws NullPointerException if the specified collection or class is null
	 */
	public static <A> A[] toArray(Collection<? extends A> collection, Class<A> clazz) {
		Object array= Array.newInstance(clazz, collection.size());
		@SuppressWarnings("unchecked")
		A[] typedArray= collection.toArray((A[]) array);
		return typedArray;
	}



JUSTIFICATION :
1.6 code like this compiles fine but throws an ArrayStoreException at run time:
        Integer[] ints = nums.toArray(new Integer[nums.size()]);

With the suggested method, clients see the type safety problem at compile time:
        Integer[] ints = Collections2.toArray(nums, Integer.class);

An added benefit of the new method is that the client doesn't have to write boilerplate code to create an array of a specific type.


---------- BEGIN SOURCE ----------
import java.util.*;

public class ArrayTypeBreak {
    public static void main(String[] args) {
        Collection<Number> nums = new ArrayList<Number>();
        nums.add(new Integer(1));
        nums.add(new Long(-1));
        
        Object[] objs = nums.toArray(new Object[0]);
        Object[] objs2 = nums.toArray(new Number[0]);
        Number[] nums2 = nums.toArray(new Number[0]);

        // No compile-time warning, but throws ArrayStoreException:
        Integer[] ints = nums.toArray(new Integer[nums.size()]);
        
        for (Integer integer : ints) {
            System.out.println(integer);
        }
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Clients can use a home-made helper method. However, such basic functionality should be shared in the JRE.

                                    

Comments



Hardware and Software, Engineered to Work Together