voliate修饰数组有作用吗_Arrays.asList()真的就把数组转换为了List集合吗?
看面试题的时候,里面提到了这个,之前都是常规的使用,把数组转换为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
方法会出现异常, remove
和 clear
方法也会出现异常。
现在只是知道了 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(); } } // 省略...}
可以看到, add
和 remove
方法都抛出了 UnsupportedOperationException
异常,这里就是关键,在调用 add
和 remove
方法时,因为是继承了 AbstractList
类,而 ArrayList
又没有重写 add
和 remove
方法,则会调用父类的方法,抛出异常。clear
方法和 add
不太一样, clear
方法又调用了 removeRange
方法,而 removeRange
方法中又执行了 it.remove();
方法,然后再经过JDK源码的一些执行,最后会执行到 remove
方法上,所以也会抛出一个异常。
到此,为什么会抛出异常的原因知道了,但是还是没弄清楚是怎么伪装成List集合使用的。
如果细心就会发现, AbstractList
实现了 List
接口,然后基于Java的多态特性,父类引用指向子类对象,自然而然就被当做了List集合使用。
到此,分析过源码之后,就知道了为什么 Arrays.asList()
没有把数组转换为 List
集合,为什么在调用 add
、 remove
和 clear
方法时会抛出异常。知道了怎么伪装成为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集合吗?相关推荐
- java基础 --- Arrays.asList():返回指定数组支持的固定大小列表
Arrays.asList():返回指定数组支持的固定大小列表 首先看下这个方法的源码注释,注意第一句,Returns a fixed-size list backed by the specifie ...
- Java 方法使用final 修饰参数的作用
Java 方法使用final 修饰参数的作用 查看全文 http://www.taodudu.cc/news/show-1232640.html 相关文章: MYSQL 数据库怎样快速的复制表以及表中 ...
- 【java】数组转list用arrays.aslist报错
现象: 数组转List用arrays.asList方法,只能用于获取数组长度,不能从转成的List中使用add和remove方法 报错:java.lang.UnsupportedOperationEx ...
- Java中static修饰符的作用
近日在做网络通信服务器和客户端的Java语言开发,碰到了获取客户端长连接Channel对象,利用唯一对象Client的获取方法getSingleClientInstance(),以为可以得到,但是显示 ...
- C++数组(数组定义方式、数组名作用、数组地址)
文章目录 1 数组概述 2 一维数组 2.1 一维数组定义方式 2.2 一维数组数组名 2.2.1 一维数组名称的作用 2.2.2 一维数组名的2种特例情况 2.3 一维数组的地址 2.4 冒泡排序 ...
- JAVA中一维数组的作用,JAVA中一维数组和二维数组的定义
在java中数组被看成是一个对象 在定义数组时,有两种定义方法:int[] a 和int a[]:第二种是C/C++对数组定义方式,对于JAVA建议采用第一种定义方式. 总的原则:任何对象在被调用之前 ...
- C语言中动态数组的作用,C语言实现动态数组
前言 在纯C语言编程中,数组的创建必须是固定的大小,因为C语言本身没有提供动态数组这种数据结构,这是一个让习惯了使用高级语言编程的人转做C开发面临的一个很头疼的问题,本篇文章就将介绍如何使用纯C语言编 ...
- 二维数组在c语言中的作用,C语言中的二维数组
1.二维数组的定义和引用 一. 数据类型 数组名[常量表达式1][常量表达式2]; (1)假如有个二维数组array[n][m],则行下标的取值范围0~n-1 (2)列下标的取值范围0~m-1 (3) ...
- c语言数组的作用是什么,C语言数组是什么
C语言数组是什么 C语言数组是什么呢?大家是否清楚呢?下面是小编分享的C语言数组的概念,欢迎大家参考! 例子:输出一个 4×4 的整数矩阵,代码如下: #include #include int ma ...
最新文章
- underscore:get elements counts of a array
- Ubuntu 16.04 安装 caffe
- 信息系统项目管理师:论项目的沟通管理
- Hibernate第一次课(1)
- FastReport.net 使用记录
- 美登杯”上海市高校大学生程序设计邀请赛 Problem E 、 小 花梨 的数组 (线段树)...
- 转:Java并发编程与高并发解决方案(一)
- SVN中的trunk branches tags
- c语言明解课后答案,《明解C语言》第三章笔记和练习题
- CCF201412-2 Z字形扫描(100分)
- 【LOJ】#2532. 「CQOI2018」社交网络
- MapReduce:详解Shuffle过程
- Adobe Photoshop CC2018软件安装教程
- 【产品经理】 产品经理进阶之路(十一):怎么看微信的公众号和百度的直达号,哪个更有优势
- 高德地图 鼠标点击后 地图上点标记跟着变化
- 微信公众号快速增粉攻略详解
- draw.io 插入 word
- c语言菜单即功能,C语言 菜单专题
- C#进行Visio二次开发之Web查看Visio图纸
- VM安装Ubuntu 16.04