html5中文学习网

您的位置: 首页 > 网络编程 > java教程 » 正文

java 源码分析Arrays.asList方法详解_java_

[ ] 已经帮助:人解决问题

最近,抽空把java Arrays 工具类的asList 方法做了源码分析,在网上整理了相关资料,记录下来,希望也能帮助读者!D5uHTML5中文学习网 - HTML5先行者学习网

Arrays工具类提供了一个方法asList, 使用该方法可以将一个变长参数或者数组转换成List 。D5uHTML5中文学习网 - HTML5先行者学习网

其源代码如下:D5uHTML5中文学习网 - HTML5先行者学习网

 /**  * 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> 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  */ @SafeVarargs public static <T> List<T> asList(T... a) {  return new ArrayList<>(a); } 

问题发现D5uHTML5中文学习网 - HTML5先行者学习网

根据上述方法的描述,我们先来编写几个例子:D5uHTML5中文学习网 - HTML5先行者学习网

/** * @author wangmengjun * */public class ArrayExample {  public static void main(String[] args) {    /**使用变长参数*/  List<String> array1 = Arrays.asList("Welcome", "to","Java", "world");  System.out.println(array1);    /**使用数组*/  List<String> array2 = Arrays.asList(new String[] {"Welcome", "to","Java", "world"});  System.out.println(array2); }}

 运行上述程序,输出如下内容。D5uHTML5中文学习网 - HTML5先行者学习网

[Welcome, to, Java, world]D5uHTML5中文学习网 - HTML5先行者学习网
[Welcome, to, Java, world]D5uHTML5中文学习网 - HTML5先行者学习网
D5uHTML5中文学习网 - HTML5先行者学习网

心血来潮,突然想在创建的列表中添加一个字符串“Cool~~~”,  走一个。D5uHTML5中文学习网 - HTML5先行者学习网

 /**使用变长参数*/  List<String> array1 = Arrays.asList("Welcome", "to","Java", "world");  array1.add("Cool~~~");

结果,遇到一个UnsupportedOperationException异常D5uHTML5中文学习网 - HTML5先行者学习网

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)

不可思议,new ArrayList<>(a)产生的列表调用add方法,竟然遇到问题。D5uHTML5中文学习网 - HTML5先行者学习网

原因查找D5uHTML5中文学习网 - HTML5先行者学习网

那么问题来了,到底发生了什么事情?带着疑问,去查看一下Arrays.asList中使用的ArrayList到底长啥样?D5uHTML5中文学习网 - HTML5先行者学习网

原来Arrays的asList方法使用的ArrayList类是一个内部定义的类,而不是java.util.ArrayList类。D5uHTML5中文学习网 - HTML5先行者学习网

其源代码如下:D5uHTML5中文学习网 - HTML5先行者学习网

 /**   * @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;    }  }

从这个内部类ArrayList的实现可以看出,它继承了抽象类java.util.AbstractList<E>, 但是没有重写add和remove方法,没有给出具体的实现。D5uHTML5中文学习网 - HTML5先行者学习网

但是,默认情况下,java.util.AbstractList类在add、set以及remove方法中,直接会抛出UnsupportedOperationException异常。AbstractList的部分源代码如下:D5uHTML5中文学习网 - HTML5先行者学习网

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();  }}

 正是因为java.util.Arrays类的内部类ArrayList没有重写add和remove方法,所以,当我们调用其add方法时,其实就是调用了AbstractList类的add方法,结果就是直接抛出UnsupportedOperationException异常。D5uHTML5中文学习网 - HTML5先行者学习网

同理,在调用remove方法,或者调用与add、remove方法相关联的其它方法(如addAll)同样会遇到UnsupportedOperationException异常。D5uHTML5中文学习网 - HTML5先行者学习网

addAll的例子:D5uHTML5中文学习网 - HTML5先行者学习网

/** * @author wangmengjun * */public class ArrayExample {  public static void main(String[] args) {    /**使用变长参数*/    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) 

set的例子:D5uHTML5中文学习网 - HTML5先行者学习网

/** * @author wangmengjun * */public class ArrayExample {  public static void main(String[] args) {    /**使用变长参数*/    List<String> array1 = Arrays.asList("Welcome", "to", "Java", "world");    System.out.println(array1);        //将Java替换成hello    array1.set(2, "hello");    System.out.println(array1);  }}

正是由于Arrays的内部类ArrayList重写了set方法,所以上述程序能够正常运行,不会再抛出UnsupportedOperationException异常。D5uHTML5中文学习网 - HTML5先行者学习网

结果如下:D5uHTML5中文学习网 - HTML5先行者学习网

[Welcome, to, Java, world]D5uHTML5中文学习网 - HTML5先行者学习网
[Welcome, to, hello, world] D5uHTML5中文学习网 - HTML5先行者学习网

使用场景D5uHTML5中文学习网 - HTML5先行者学习网

从上述的例子和简单分析来看,Arrays工具类提供了一个方法asList, 使用该方法可以将一个变长参数或者数组转换成List 。D5uHTML5中文学习网 - HTML5先行者学习网

但是,生成的List的长度是固定的;能够进行修改操作(比如,修改某个位置的元素);不能执行影响长度的操作(如add、remove等操作)。会抛出UnsupportedOperationException异常。D5uHTML5中文学习网 - HTML5先行者学习网

Arrays.asList比较适合那些已经有数组数据或者一些元素,而需要快速构建一个List,只用于读取操作,而不进行添加或删除操作的场景。D5uHTML5中文学习网 - HTML5先行者学习网

如果,想要根据已知数组数据,快速获取一个可进行增删改查的列表List,一个比较简单的方法如下:D5uHTML5中文学习网 - HTML5先行者学习网

重新使用java.util.ArrayList包装一层。D5uHTML5中文学习网 - HTML5先行者学习网

/** * @author wangmengjun * */public class ArrayExample {  public static void main(String[] args) {    /**使用变长参数*/    List<String> array1 = new ArrayList<>(Arrays.asList("Welcome", "to", "Java", "world"));    System.out.println(array1);    array1.add("Cool~~~");    System.out.println(array1);  }}

结果如下:D5uHTML5中文学习网 - HTML5先行者学习网

[Welcome, to, Java, world]D5uHTML5中文学习网 - HTML5先行者学习网
[Welcome, to, Java, world, Cool~~~]D5uHTML5中文学习网 - HTML5先行者学习网

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!D5uHTML5中文学习网 - HTML5先行者学习网

(责任编辑:)
推荐书籍
推荐资讯
关于HTML5先行者 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助