Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

The Subtle Differences in toArray() Behavior Between ArrayList and Arrays.asList

Tech May 9 3

Consider the following code snippet:

List<String> list = new ArrayList<>();
list.add("1");
Object[] array = list.toArray();
array[0] = 1;
System.out.println(Arrays.toString(array));

This executes without error. However, modifying the code to use Arrays.asList leads to an ArrayStoreException:

List<String> list = Arrays.asList("1");
Object[] array = list.toArray();
array[0] = 1;
System.out.println(Arrays.toString(array));

Both toArray() methods are declared to return Object[], but their runtime behavior differs due to underlying implementations.

In java.util.ArrayList, the toArray() method creates a new Object[] array by copying the internal elementData array, which is initialized as an Object[]. Therefore, assigning a Integer to an element is permissible.

// Simplified view of ArrayList.toArray()
public Object[] toArray() {
    return Arrays.copyOf(elementData, size);
}

In contrast, the ArrayList returned by Arrays.asList is a fixed-size wrapper around the provided array. Its toArray() method returns a clone of the backing array. Due to type erasure and the varargs mechanism, the backing array's actual type at runtime is String[], not Object[].

// Internal representation in Arrays.asList
String[] backingArray = {"1"};
List<String> wrappedList = Arrays.asList(backingArray);
Object[] result = wrappedList.toArray(); // Actually returns String[]

Thus, attempting to store an Integer in this array causes an ArrayStoreException because the runtime type is String[].

This discrepancy was identified as a bug because the Collection.toArray() contract specifies returning Object[], but the implementation for Arrays.asList violated this by returning an array of a more specific type. The issue was reported in OpenJDK around 2005 and finally resolved in JDK 9 (2015).

The fix in JDK 9 modified Arrays.asList's toArray() to always return a new Object[] array, aligning it with java.util.ArrayList:

// JDK 9+ implementation for Arrays.asList ArrayList
public Object[] toArray() {
    return Arrays.copyOf(a, a.length, Object[].class);
}

This change, however, introduced a backward compatibility issue. Code that relied on the previous behavior, such as casting the returned array to a more specific type, would break:

// Works in JDK 8, throws ClassCastException in JDK 9+
String[] strings = (String[]) Arrays.asList("foo", "bar").toArray();

To mitigate this, some JDK 8 implementations included special handling in java.util.ArrayList constructors that accept collections, ensuring compatibility. For example, Oracle JDK 8 and Eclipse Temurin OpenJDK 8 had different internal workarounds.

When using the parameterized toArray(T[] a) method, performance considerations arise. The common idiom toArray(new T[0]) is generally efficient, as modern JVMs optimize zero-length array allocations. Pre-sizing the array (e.g., toArray(new T[list.size()])) can avoid an extra array copy but may waste memory if the list size changes concurrently in a non-thread-safe manner.

// Example of toArray with a pre-sized array
List<String> items = new ArrayList<>();
items.add("A");
String[] output = items.toArray(new String[0]);

Since ArrayList is not thread-safe, concurrent modifications leading to size changes should be managed externally, not relied upon for array sizing optimizations.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.