看面试题的时候,里面提到了这个,之前都是常规的使用,把数组转换为List集合,程序每次也都正常的运行,没在意过这个问题。看到这个问题时直接懵了,难道我之前的使用是错误的吗?后来查了资料确实是有点问题,Arrays.asList()还就真就没把数组转换为List集合,源码底层还是一个数组!。

话不多说。直接上代码,结果才是唯一真理。

再简单不过的一个把数组转换为List集合的例子。

public class ArraysTest {    public static void main(String[] args) {        String[] strings = new String[]{"张三","李四","王二","麻子"};        Listlist = Arrays.asList(strings);        list.add("啥也不会的程序员");    }}

可以看到程序的第17行报了一个异常,17行就对应着 list.add("啥也不会的程序员");这个方法。出现异常的原因就是调用了 add方法。一开始就说了,底层还是一个数组,而数组的一个重要特点就是,一旦长度确定之后就不可以改变。所以也就导致了, add方法出现异常。而且不止 add方法会出现异常, removeclear方法也会出现异常。

现在只是知道了 Arrays.asList()在执行 add等方法的时候会出现异常,但是具体原因是什么还不清楚,而且如果底层是数组的话,怎么又会说把数组转换为List集合呢?

想要知道原理,就要分析源码了。

先看看 Arrays.asList()这个方法的源码是怎么样的

public static ListasList(T... a) {    return new ArrayList<>(a);}

可以看到asList这个方法中并没有什么特殊的代码,只不过传入了一个可变参数,然后又创建了一个 ArrayList对象并返回。那好,就继续看ArrayList的源码。

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) {            a = Objects.requireNonNull(array);        }    // 后面的省略,不是重点}

可以发现,这个类是一个私有的静态内部类。并且有一个带参构造器,构造器需要传入一个泛型数组,而后这个泛型数组在经过非空判断后赋值给了final修饰的泛型数组a。哦,到了这里就会发现,其实本质还是一个数组,一个泛型数组,只不过在这个数组外面套上一个 ArrayList类的外壳。

到了这里就会知道了,其实本质还是一个数组,可是,知道了是数组了,那么异常又是哪里来的呢?平常使用中又是怎么把它伪装成List集合使用的呢?既然不清楚,那就继续看源码。ArrayList类没有关于异常的源码,那就看它父类 AbstractList的源码。

AbstractList的部分源码

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {    public boolean add(E e) {        add(size(), e);        return true;    }        public void add(int index, E element) {        throw new UnsupportedOperationException();    }    public E remove(int index) {        throw new UnsupportedOperationException();    }        public void clear() {        removeRange(0, size());    }        protected void removeRange(int fromIndex, int toIndex) {        ListIterator it = listIterator(fromIndex);        for (int i=0, n=toIndex-fromIndex; i            it.next();            it.remove();        }    }    // 省略...}

可以看到, addremove方法都抛出了 UnsupportedOperationException异常,这里就是关键,在调用 addremove方法时,因为是继承了 AbstractList类,而 ArrayList又没有重写 addremove方法,则会调用父类的方法,抛出异常。clear方法和 add不太一样, clear方法又调用了 removeRange方法,而 removeRange方法中又执行了 it.remove();方法,然后再经过JDK源码的一些执行,最后会执行到 remove方法上,所以也会抛出一个异常。

到此,为什么会抛出异常的原因知道了,但是还是没弄清楚是怎么伪装成List集合使用的。

如果细心就会发现, AbstractList实现了 List接口,然后基于Java的多态特性,父类引用指向子类对象,自然而然就被当做了List集合使用。

到此,分析过源码之后,就知道了为什么 Arrays.asList()没有把数组转换为 List集合,为什么在调用 addremoveclear方法时会抛出异常。知道了怎么伪装成为List集合使用的。

总结就是:Arrays.asList()并没有把数组转换为List集合,而是对其套了一个自己的内部类的壳,而这个类又实现了List接口,从而通过多态,父类引用指向子类对象,达到List集合的作用效果。

那么又如何正确的将数组转换为List集合呢?

1、手动实现

private staticList arrayToList(T[] array){        Listlist = new ArrayList<>();        for (T t:array){            list.add(t);        }        return list;}

2、最简单的方法

String[] strings = new String[]{"张三","李四","王二","麻子"};List<String> list1 = new ArrayList<>(Arrays.asList(strings));

3、Java8的Stream

String[] strings = new String[]{"张三","李四","王二","麻子"};List<String> list = Arrays.stream(strings).collect(Collectors.toList());

voliate修饰数组有作用吗_Arrays.asList()真的就把数组转换为了List集合吗?相关推荐

  1. java基础 --- Arrays.asList():返回指定数组支持的固定大小列表

    Arrays.asList():返回指定数组支持的固定大小列表 首先看下这个方法的源码注释,注意第一句,Returns a fixed-size list backed by the specifie ...

  2. Java 方法使用final 修饰参数的作用

    Java 方法使用final 修饰参数的作用 查看全文 http://www.taodudu.cc/news/show-1232640.html 相关文章: MYSQL 数据库怎样快速的复制表以及表中 ...

  3. 【java】数组转list用arrays.aslist报错

    现象: 数组转List用arrays.asList方法,只能用于获取数组长度,不能从转成的List中使用add和remove方法 报错:java.lang.UnsupportedOperationEx ...

  4. Java中static修饰符的作用

    近日在做网络通信服务器和客户端的Java语言开发,碰到了获取客户端长连接Channel对象,利用唯一对象Client的获取方法getSingleClientInstance(),以为可以得到,但是显示 ...

  5. C++数组(数组定义方式、数组名作用、数组地址)

    文章目录 1 数组概述 2 一维数组 2.1 一维数组定义方式 2.2 一维数组数组名 2.2.1 一维数组名称的作用 2.2.2 一维数组名的2种特例情况 2.3 一维数组的地址 2.4 冒泡排序 ...

  6. JAVA中一维数组的作用,JAVA中一维数组和二维数组的定义

    在java中数组被看成是一个对象 在定义数组时,有两种定义方法:int[] a 和int a[]:第二种是C/C++对数组定义方式,对于JAVA建议采用第一种定义方式. 总的原则:任何对象在被调用之前 ...

  7. C语言中动态数组的作用,C语言实现动态数组

    前言 在纯C语言编程中,数组的创建必须是固定的大小,因为C语言本身没有提供动态数组这种数据结构,这是一个让习惯了使用高级语言编程的人转做C开发面临的一个很头疼的问题,本篇文章就将介绍如何使用纯C语言编 ...

  8. 二维数组在c语言中的作用,C语言中的二维数组

    1.二维数组的定义和引用 一. 数据类型 数组名[常量表达式1][常量表达式2]; (1)假如有个二维数组array[n][m],则行下标的取值范围0~n-1 (2)列下标的取值范围0~m-1 (3) ...

  9. c语言数组的作用是什么,C语言数组是什么

    C语言数组是什么 C语言数组是什么呢?大家是否清楚呢?下面是小编分享的C语言数组的概念,欢迎大家参考! 例子:输出一个 4×4 的整数矩阵,代码如下: #include #include int ma ...

最新文章

  1. underscore:get elements counts of a array
  2. Ubuntu 16.04 安装 caffe
  3. 信息系统项目管理师:论项目的沟通管理
  4. Hibernate第一次课(1)
  5. FastReport.net 使用记录
  6. 美登杯”上海市高校大学生程序设计邀请赛 Problem E 、 小 花梨 的数组 (线段树)...
  7. 转:Java并发编程与高并发解决方案(一)
  8. SVN中的trunk branches tags
  9. c语言明解课后答案,《明解C语言》第三章笔记和练习题
  10. CCF201412-2 Z字形扫描(100分)
  11. 【LOJ】#2532. 「CQOI2018」社交网络
  12. MapReduce:详解Shuffle过程
  13. Adobe Photoshop CC2018软件安装教程
  14. 【产品经理】 产品经理进阶之路(十一):怎么看微信的公众号和百度的直达号,哪个更有优势
  15. 高德地图 鼠标点击后 地图上点标记跟着变化
  16. 微信公众号快速增粉攻略详解
  17. draw.io 插入 word
  18. c语言菜单即功能,C语言 菜单专题
  19. C#进行Visio二次开发之Web查看Visio图纸
  20. VM安装Ubuntu 16.04

热门文章

  1. Android Studio中架包打包和依赖冲突解决
  2. JADAK收购RFID方案商SkyeTek,增强竞争力
  3. 多线程——生产者与消费者(多)1.5新锁,问题解决
  4. android如何实现开机自动启动Service或app
  5. hive的multi-distinct可能带来性能恶化
  6. [PHP] 访问MySQL
  7. 比特币现金驱动的社交媒体平台备忘录继续蓬勃发展
  8. 对ETC上线Coinbase反应的众生相
  9. 宜信开源|数据库审核软件Themis的规则解析与部署攻略
  10. gnupg环境搭建时遇到的问题