Arrays工具类提供了一些比较实用的方法,比如sort, binarySearch, fill等。其中还有一个
asList
方法,此方法能够将一个变长参数或者数组转换成List。
但是,这个生成的List,它是固定长度的,如果对其进行add或者remove的操作,会抛出UnsupportedOperationException ,为什么会这样呢?
带着疑问,查看一下Arrays的源码,可以得到问题的结果。
方法asList返回的是new ArrayList<T>(a)。但是,这个ArrayList并不是java.util.ArrayList,它是一个Arrays类中的重新定义的内部类。
具体的实现如下:
从这个内部类ArrayList的实现可以看出,它继承了类AbstractList<E>,但是没有重写add和remove方法,没有给出具体的实现。查看一下AbstractList类中对add和remove方法的定义,如果一个list不支持add和remove就会抛出UnsupportedOperationException。
至此,为什么Arrays.asList产生的List是不可添加或者删除,否则会产生UnsupportedOperationException,就可以得到解释了。
如果我们想把一个变长或者数据转变成List, 而且期望这个List能够进行add或者remove操作,那该怎么做呢?
我们可以写一个类似的方法,里面直接采用java.util.ArrayList即可。
比如:
测试代码如下:
输出结果:
[Larry, Moe, Curly]
[[Spring, Summer, Autumn, Winter]]
[Larry, Moe, Curly, Hello]
但是,这个生成的List,它是固定长度的,如果对其进行add或者remove的操作,会抛出UnsupportedOperationException ,为什么会这样呢?
带着疑问,查看一下Arrays的源码,可以得到问题的结果。
- /**
- * 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 <tt>Collection.toArray</tt>. 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> stooges = 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.
- * @see Collection#toArray()
- */
- public static <T> List<T> asList(T... a) {
- return new ArrayList<T>(a);
方法asList返回的是new ArrayList<T>(a)。但是,这个ArrayList并不是java.util.ArrayList,它是一个Arrays类中的重新定义的内部类。
具体的实现如下:
- /**
- * @serial include
- */
- private static class ArrayList<E> extends AbstractList<E>
- implements RandomAccess, java.io.Serializable
- {
- private static final long serialVersionUID = -2764017481108945198L;
- private Object[] a;
- ArrayList(E[] array) {
- if (array==null)
- throw new NullPointerException();
- a = array;
- }
- public int size() {
- return a.length;
- }
- public Object[] toArray() {
- return (Object[])a.clone();
- }
- public E get(int index) {
- return (E)a[index];
- }
- public E set(int index, E element) {
- Object oldValue = a[index];
- a[index] = element;
- return (E)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;
- }
- }
从这个内部类ArrayList的实现可以看出,它继承了类AbstractList<E>,但是没有重写add和remove方法,没有给出具体的实现。查看一下AbstractList类中对add和remove方法的定义,如果一个list不支持add和remove就会抛出UnsupportedOperationException。
- public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
- /**
- * Sole constructor. (For invocation by subclass constructors, typically
- * implicit.)
- */
- protected AbstractList() {
- }
- /**
- * Appends the specified element to the end of this List (optional
- * operation). <p>
- *
- * This implementation calls <tt>add(size(), o)</tt>.<p>
- *
- * Note that this implementation throws an
- * <tt>UnsupportedOperationException</tt> unless <tt>add(int, Object)</tt>
- * is overridden.
- *
- * @param o element to be appended to this list.
- *
- * @return <tt>true</tt> (as per the general contract of
- * <tt>Collection.add</tt>).
- *
- * @throws UnsupportedOperationException if the <tt>add</tt> method is not
- * supported by this Set.
- *
- * @throws ClassCastException if the class of the specified element
- * prevents it from being added to this set.
- *
- * @throws IllegalArgumentException some aspect of this element prevents
- * it from being added to this collection.
- */
- public boolean add(E o) {
- add(size(), o);
- return true;
- }
- /**
- * Inserts the specified element at the specified position in this list
- * (optional operation). Shifts the element currently at that position
- * (if any) and any subsequent elements to the right (adds one to their
- * indices).<p>
- *
- * This implementation always throws an UnsupportedOperationException.
- *
- * @param index index at which the specified element is to be inserted.
- * @param element element to be inserted.
- *
- * @throws UnsupportedOperationException if the <tt>add</tt> method is not
- * supported by this list.
- * @throws ClassCastException if the class of the specified element
- * prevents it from being added to this list.
- * @throws IllegalArgumentException if some aspect of the specified
- * element prevents it from being added to this list.
- * @throws IndexOutOfBoundsException index is out of range (<tt>index <
- * 0 || index > size()</tt>).
- */
- public void add(int index, E element) {
- throw new UnsupportedOperationException();
- }
- /**
- * Removes the element at the specified position in this list (optional
- * operation). Shifts any subsequent elements to the left (subtracts one
- * from their indices). Returns the element that was removed from the
- * list.<p>
- *
- * This implementation always throws an
- * <tt>UnsupportedOperationException</tt>.
- *
- * @param index the index of the element to remove.
- * @return the element previously at the specified position.
- *
- * @throws UnsupportedOperationException if the <tt>remove</tt> method is
- * not supported by this list.
- * @throws IndexOutOfBoundsException if the specified index is out of
- * range (<tt>index < 0 || index >= size()</tt>).
- */
- public E remove(int index) {
- throw new UnsupportedOperationException();
- }
- }
至此,为什么Arrays.asList产生的List是不可添加或者删除,否则会产生UnsupportedOperationException,就可以得到解释了。
如果我们想把一个变长或者数据转变成List, 而且期望这个List能够进行add或者remove操作,那该怎么做呢?
我们可以写一个类似的方法,里面直接采用java.util.ArrayList即可。
比如:
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- public class MyArrays {
- public static <T> List<T> asList(T... a) {
- List<T> list = new ArrayList<T>();
- Collections.addAll(list, a);
- return list;
- }
- }
测试代码如下:
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- public class Test {
- @SuppressWarnings("unchecked")
- public static void main(String[] args) {
- List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
- print(stooges);
- List<List<String>> seasonsList = Arrays.asList(retrieveSeasonsList());
- print(seasonsList);
- /*
- * 自己实现一个asList方法,能够添加和删除。
- */
- List<String> list = MyArrays.asList("Larry", "Moe", "Curly");
- list.add("Hello");
- print(list);
- }
- private static <T> void print(List<T> list) {
- System.out.println(list);
- }
- private static List<String> retrieveSeasonsList() {
- List<String> seasonsList = new ArrayList<String>();
- seasonsList.add("Spring");
- seasonsList.add("Summer");
- seasonsList.add("Autumn");
- seasonsList.add("Winter");
- return seasonsList;
- }
- }
输出结果:
[Larry, Moe, Curly]
[[Spring, Summer, Autumn, Winter]]
[Larry, Moe, Curly, Hello]