EVALUATION
One problem with the suggested fix is the problem of what
happens if the collection is being concurrently modified.
The c.size() information may be inaccurate by the time c.toArray()
is called, possibly leading to the method (rarely) returning an array
with trailing null elements. Worse, if the collection allows null
elements, there is no way to tell if the trailing nulls are part of
the collection or not.
An attempt to salvage the implementation is to code like this:
return c.<T>toArray((T[])Array.newInstance(t, 0));
but that pays a penalty for an extra empty array allocation for each
call to toArray. Normally a user could write the code more efficiently
by saving an empty array of the desired type
for use on each call to c.toArray(EMPTY_ARRAY)
The small increase in elegance is not worth the increase in the size of the
API and the small annoying performance penalty.
Josh Bloch writes:
---------------------------------------------
This is perfectly feasible but I'm not sure
it's a good idea. This is the one place where I find the array type
token more natural than the Class object. I like the fact that you
get back the same zero-length array that you passed in if the
collection is of size zero. I'm not saying it's a bad idea; the call
site looks nicer with the class literal. So I can certainly live with
it if that's what people want.
---------------------------------------------
Therefore I am closing this as Not A Defect.
02-09-2005
SUGGESTED FIX
--- /tmp/geta8166 2005-09-01 16:03:13.680432616 -0700
+++ Collections.java 2005-06-01 19:37:12.000000000 -0700
@@ -3511,4 +3511,38 @@
result |= c.add(e);
return result;
}
+
+ /**
+ * Returns a new array containing all of the elements in the
+ * specified collection. The array is allocated with the runtime
+ * element type of the specified class and the size of the
+ * collection.
+ *
+ * <p>If the collection makes any guarantees as to what order its
+ * elements are returned by its iterator, this method must return
+ * the elements in the same order.
+ *
+ * @param c a collection
+ * @param t a class respresenting the component type of the
+ * returned array. Must represent a reference type.
+ * @return a newly allocated array of the specified type
+ * containing the elements of the collection.
+ *
+ * @throws ArrayStoreException if the runtime type of the class is
+ * not a supertype of the runtime type of every element in the
+ * collection.
+ * @throws IllegalArgumentException if the class doesn't
+ * represent a reference type.
+ * @throws NullPointerException if either of the arguments are
+ * <tt>null</tt>.
+ *
+ * @see java.util.Collection.toArray(Object[])
+ * @since 1.6
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T[] toArray(Collection<?> c, Class<T> t) {
+ if (t.isPrimitive())
+ throw new IllegalArgumentException();
+ return c.<T>toArray((T[])Array.newInstance(t, c.size()));
+ }
}
01-09-2005
EVALUATION
A very good idea.
###@###.### 2004-08-17
An alternative would be to add a method to the Collection interface. However,
this would not be backwards compatible with existing implementations of this
interface.
###@###.### 2004-11-29 19:56:50 GMT
29-11-2004
CONVERTED DATA
BugTraq+ Release Management Values
COMMIT TO FIX:
mustang