United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-6260652 : (coll) Arrays.asList(x).toArray().getClass() should be Object[].class

Details
Type:
Bug
Submit Date:
2005-04-25
Status:
Open
Updated Date:
2013-10-02
Project Name:
JDK
Resolved Date:
Component:
core-libs
OS:
linux,windows_xp
Sub-Component:
java.util:collections
CPU:
x86
Priority:
P3
Resolution:
Unresolved
Affected Versions:
5.0,6
Targeted Versions:
tbd_major

Related Reports
Duplicate:

Sub Tasks

Description
FULL PRODUCT VERSION :
java version "1.5.0_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_02-b09)
Java HotSpot(TM) Client VM (build 1.5.0_02-b09, mixed mode, sharing)


ADDITIONAL OS VERSION INFORMATION :
Linux itppc27 2.4.19-4GB #1 Mon Aug 4 23:38:42 UTC 2003 i686 unknown

A DESCRIPTION OF THE PROBLEM :
The Collection documentation claims that

    collection.toArray()

is "identical in function" to

    collection.toArray(new Object[0]);

However, the implementation of Arrays.asList does not follow this: If created with an array of a subtype (e.g. String[]), its toArray() will return an array of the same type (because it use clone()) instead of an Object[].

If one later tries to store non-Strings (or whatever) in that array, an ArrayStoreException is thrown.

Either the Arrays.asList() implementation (which may return an array of component type not Object) or the Collection toArray documentation (which does not allow argumentless toArray() to return arrays of subtypes of Object) is wrong.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute code.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
[Ljava.lang.Object;@10b62c9
[Ljava.lang.Object;@82ba41

ACTUAL -
[Ljava.lang.String;@10b62c9
[Ljava.lang.Object;@82ba41


REPRODUCIBILITY :
This bug can be reproduced always.

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


public class ToArray
{
    public static void main(String[] args)
    {
        List l = Arrays.asList(args);

        System.out.println(l.toArray());
        System.out.println(l.toArray(new Object[0]));
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Only use toArray(Object[]).
###@###.### 2005-04-25 12:45:46 GMT

                                    

Comments
This is a long standing issue and what I can tell, there haven't been too many reports of it. I don't see any strong reason to try to squeeze this into jdk8 so deferring it to early jdk9 seems reasonable (to me).
                                     
2013-09-28
A testing datapoint, the current jtreg jdk_core regression suite runs successfully when the toArray method is changed to:

return Arrays.copyOf(a, 0, a.length, Object.class);

This is by no means exhaustive but perhaps a useful indication that this change might be safe.

Nonetheless, any objections to deferring this from 8?
                                     
2013-09-27
SUGGESTED FIX

--- /u/martin/ws/mustang/src/share/classes/java/util/Arrays.java	2005-08-11 11:04:21.718074000 -0700
+++ /u/martin/ws/toArray/src/share/classes/java/util/Arrays.java	2005-08-27 18:01:03.522592000 -0700
@@ -2949,7 +2948,7 @@
 	implements RandomAccess, java.io.Serializable
     {
         private static final long serialVersionUID = -2764017481108945198L;
-	private Object[] a;
+	private final E[] a;
 
 	ArrayList(E[] array) {
             if (array==null)
@@ -2962,17 +2961,27 @@
 	}
 
 	public Object[] toArray() {
-	    return (Object[])a.clone();
+	    return Arrays.copyOf(a, a.length, Object[].class);
+	}
+
+	public <T> T[] toArray(T[] a) {
+	    int size = size();
+	    if (a.length < size)
+		return Arrays.copyOf(this.a, size, (Class<T[]>) a.getClass());
+	    System.arraycopy(this.a, 0, a, 0, size);
+	    if (a.length > size)
+		a[size] = null;
+	    return a;
 	}
 
 	public E get(int index) {
-	    return (E)a[index];
+	    return a[index];
 	}
 
 	public E set(int index, E element) {
-	    Object oldValue = a[index];
+	    E oldValue = a[index];
 	    a[index] = element;
-	    return (E)oldValue;
+	    return oldValue;
 	}
 
         public int indexOf(Object o) {
                                     
2005-08-07
EVALUATION

The submitter is correct.
toArray() must always return an object of precise type Object[].
                                     
2005-08-07



Hardware and Software, Engineered to Work Together