Recently, I took the time to analyze the asList method of the java Arrays tool class, sorted out relevant information online, and recorded it, hoping to help readers!
The Arrays tool class provides a method asList, which uses this method to convert a variable-length parameter or array into a List.
The source code is as follows:
/** * Returns a fixed-size list backed by the specified array. (Changes to * the returned list "write through" to the array.) This method acts * as bridge between array-based and collection-based APIs, in * combination with {@link Collection#toArray}. The returned list is * serializable and implements {@link RandomAccess}. * * <p>This method also provides a convenient way to create a fixed-size * list initialized to contain several elements: * <pre> * List<String> stands = Arrays.asList("Larry", "Moe", "Curly"); * </pre> * * @param a the array by which the list will be backed * @return a list view of the specified array */ @SafeVarargs public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }Problem discovery
Based on the description of the above method, let’s first write a few examples:
/** * @author wangmengjun * */public class ArrayExample { public static void main(String[] args) { /**Use variable length parameters*/ List<String> array1 = Arrays.asList("Welcome", "to","Java", "world"); System.out.println(array1); /**Use array*/ List<String> array2 = Arrays.asList(new String[] {"Welcome", "to","Java", "world"}); System.out.println(array2); }}Run the above program and output the following content.
[Welcome, to, Java, world]
[Welcome, to, Java, world]
On a whim, I suddenly wanted to add a string "Cool~~~" to the created list and go one.
/**Use variable length parameters*/ List<String> array1 = Arrays.asList("Welcome", "to","Java", "world"); array1.add("Cool~~~");As a result, an UnsupportedOperationException was encountered:
Exception in thread "main" java.lang.UnsupportedOperationException at java.util.AbstractList.add(Unknown Source) at java.util.AbstractList.add(Unknown Source) at test.ArrayExample.main(ArrayExample.java:36)
Incredibly, the list generated by new ArrayList<>(a) actually encountered a problem.
Reason search
So the question is, what exactly happened? With questions, check what the ArrayList used in Arrays.asList looks like?
It turns out that the ArrayList class used by the asList method of Arrays is an internally defined class, not the java.util.ArrayList class.
The source code is as follows:
/** * @serial include */ private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable { private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] array) { if (array==null) throw new NullPointerException(); a = array; } public int size() { return a.length; } public Object[] toArray() { return a.clone(); } public <T> T[] toArray(T[] a) { int size = size(); if (a.length < size) return Arrays.copyOf(this.a, size, (Class<? extends 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 a[index]; } public E set(int index, E element) { E oldValue = a[index]; a[index] = element; return oldValue; } public int indexOf(Object o) { if (o==null) { for (int i=0; i<a.length; i++) if (a[i]==null) return i; } else { for (int i=0; i<a.length; i++) if (o.equals(a[i])) return i; } return -1; } public boolean contains(Object o) { return indexOf(o) != -1; } }From the implementation of this inner class ArrayList, it can be seen that it inherits the abstract class java.util.AbstractList<E>, but the add and remove methods are not overridden, and the specific implementation is not given.
However, by default, the java.util.AbstractList class will directly throw an UnsupportedOperationException in the add, set and remove methods. Some of the source codes of AbstractList are as follows:
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { /** * Sole constructor. (For invocation by subclass constructors, typically * implicit.) */ protected AbstractList() { } public E set(int index, E element) { throw new UnsupportedOperationException(); } /** * {@inheritDoc} * * <p>This implementation always throws an * {@code UnsupportedOperationException}. * * @throws UnsupportedOperationException {@inheritDoc} * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} * @throws IndexOutOfBoundsException {@inheritDoc} */ public void add(int index, E element) { throw new UnsupportedOperationException(); } /** * {@inheritDoc} * * <p>This implementation always throws an * {@code UnsupportedOperationException}. * * @throws UnsupportedOperationException {@inheritDoc} * @throws IndexOutOfBoundsException {@inheritDoc} */ public E remove(int index) { throw new UnsupportedOperationException(); }}It is precisely because the inner class ArrayList of java.util.Arrays class does not override the add and remove methods, so when we call its add method, we actually call the add method of the AbstractList class, and the result is that the UnsupportedOperationException is directly thrown.
Similarly, when calling the remove method, or calling other methods associated with the add and remove methods (such as addAll), you will also encounter the UnsupportedOperationException exception.
Example of addAll:
/** * @author wangmengjun * */public class ArrayExample { public static void main(String[] args) { /**Use variable length parameters*/ List<String> array1 = Arrays.asList("Welcome", "to", "Java", "world"); array1.addAll(Arrays.asList("AAA", "BBB")); }}Exception in thread "main" java.lang.UnsupportedOperationException at java.util.AbstractList.add(Unknown Source) at java.util.AbstractList.add(Unknown Source) at java.util.AbstractCollection.addAll(Unknown Source) at test.ArrayExample.main(ArrayExample.java:36)
Example of set:
/** * @author wangmengjun * */public class ArrayExample { public static void main(String[] args) { /**Use variable length parameters*/ List<String> array1 = Arrays.asList("Welcome", "to", "Java", "world"); System.out.println(array1); //Replace Java with hello array1.set(2, "hello"); System.out.println(array1); }}It is precisely because Arrays' internal class ArrayList rewrites the set method, so the above program can run normally and will not throw UnsupportedOperationException exception.
The results are as follows:
[Welcome, to, Java, world]
[Welcome, to, hello, world]
Use scenarios
Judging from the above examples and simple analysis, the Arrays tool class provides a method asList, which can convert a variable-length parameter or array into a List.
However, the length of the generated List is fixed; it can perform modification operations (such as modifying elements at a certain position); it cannot perform operations that affect the length (such as add, remove, etc.). An UnsupportedOperationException exception will be thrown.
Arrays.asList is more suitable for scenarios where there is already array data or some elements, but it is necessary to quickly build a List, which is only used for read operations, and does not perform add or delete operations.
If you want to quickly obtain a list of lists that can be added, deleted, modified and checked based on known array data, a relatively simple method is as follows:
Reuse java.util.ArrayList to wrap a layer.
/** * @author wangmengjun * */public class ArrayExample { public static void main(String[] args) { /**Use variable length parameters*/ List<String> array1 = new ArrayList<>(Arrays.asList("Welcome", "to", "Java", "world")); System.out.println(array1); array1.add("Cool~~~"); System.out.println(array1); }}The results are as follows:
[Welcome, to, Java, world]
[Welcome, to, Java, world, Cool~~~]
Thank you for reading, I hope it can help you. Thank you for your support for this site!