Arrays.asList()得到的是真的ArrayList?操作修改集合大坑

一、前言

今天在看阿里Java规范的时候看到一条规范,经常使用,却一直没有注意的一条!

相信大家应该踩过这个坑,下面来看一看阿里规范里的内容:

【强制】使用工具类 Arrays.asList() 把数组转换成集合时,不能使用其修改集合相关的方法,它的 add / remove / clear 方法会抛出 UnsupportedOperationException 异常。

『说明』:asList 的返回对象是一个 Arrays 内部类并没有实现集合的修改方法

Arrays.asList 体现的是适配器模式,只是转换接口,后台的数据仍是数组

java 复制代码
String[] str = new String[]{ "yang", "guan", "bao" };
List list = Arrays.asList(str);

第一种情况:list.add("yangguanbao"); 运行时异常。

第二种情况:str[0] = "change"; list 中的元素也会随之修改,反之亦然。

想要最新版Java开发手册(黄山版)的可以自行下载一下:

黄山版(2022.2.3发布)下载链接

还请点个微信公众号关注哈,在文章最后!

下面我们来从例子和源码来详细看一下是不是如此!!

二、例子测试

1. 添加元素

java 复制代码
String[] arr = {"Hello", "World"};
List<String> stringList = Arrays.asList(arr);

stringList.add("报错了!");

System.out.println(stringList);

我们看到如文档所说,报了UnsupportedOperationException异常,

UnsupportedOperationException是Java编程语言中的一个异常,它表示不支持当前操作或方法。 当程序尝试执行某个操作或调用某个方法,而该操作或方法不被支持时,就会抛出此异常。

2. 修改数组

java 复制代码
String[] arr = {"Hello", "World"};
List<String> stringList = Arrays.asList(arr);

arr[0] = "修改了呢";
System.out.println(stringList);

我们可以看到,集合随着数组的变化而变化!

原因是这样的:

Arrays.asList()方法返回的集合是基于原始数组的,也就是说,它不会创建一个新的集合对象,而是将原始数组作为集合的底层实现。因此,当您更改原始数组时,通过Arrays.asList()方法得到的集合元素也会随之改变。

3. 提醒

基本数据类型要使用包装类型,不然会有问题!

java 复制代码
int[] ints = {1,2};
List<int[]> ints1 = Arrays.asList(ints);
for (int[] ints2 : ints1) {
    System.out.println(ints2);
}
System.out.println(ints1.size());

我们可以看到集合的数量为1,这是什么原因呢?

原因是:

由于Java中的泛型不支持基本类型,所以它会将整个数组视为单个元素添加到列表中。

三、源码查看究竟

看了一下源码明明new了一个ArrayList:

java 复制代码
public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}

为什么不能操作修改集合呢?

我们在点进去这个ArrayList构造方法,你会发现,这个ArrayList非ArrayList!!!!

是不是有点懵逼,我们先看一下这俩个的UML图

这个ArrayList是Arrays类的一个内部类,继承了AbstractList<E>类,但是只重写了一些方法,没有重写add、remove、clear等操作集合的方法!所以会出现UnsupportedOperationException异常!

『在看一下源码』

java 复制代码
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);
        }
    }

明明有ArrayList为什么还要写一个内部类呢?

主要是为了提高代码的效率和简洁性。 由于 Arrays.asList() 返回的 List 对象是一个视图,它只是一个包装了原始数组的列表,并不需要额外的空间来存储元素。 因此,通过 Arrays.asList() 方法将一个数组转换成 List 可以避免创建一个新的 ArrayList 对象,从而提高代码的效率和简洁性。

四、总结

我们从阿里开发手册中知道了Arrays.asList()的注意事项,自己进一步的通过例子来进行实践,最后通过源码角度来知道Arrays.asList()的原理!

我们知道了:

使用工具类 Arrays.asList() 把数组转换成集合时,不能使用其修改集合相关的方法,它的 add / remove / clear 方法会抛出 UnsupportedOperationException 异常。

更改原始数组时,通过Arrays.asList()方法得到的集合元素也会随之改变

由于Java中的泛型不支持基本类型,所以它会将整个数组视为单个元素添加到列表中。

知道 Arrays.asList() 的返回值是ArrayList,它是Arrays类的一个内部类,为了提高代码的效率和简洁性

以后使用就要注意这些问题!!!


看到这里了,还请动一下您的发财小手,关注一下公众号:『小王博客基地』!!谢谢您的关注!!文章首发看!!!

建了一个IT交流群,欢迎大家加入,过期加我拉你们进哈!

相关推荐
柯349几秒前
JVM-类加载机制
java·开发语言·jvm
风雨无阻fywz5 分钟前
java 类的实例化过程,其中的相关顺序 包括有继承的子类等复杂情况,静态成员变量的初始化顺序,这其中jvm在干什么
java·开发语言·jvm
沃野_juededa34 分钟前
关于uniapp 中uview input组件设置为readonly 或者disabled input区域不可点击问题
java·前端·uni-app
红烧柯基3 小时前
解决redis序列号和反序列化问题
java·数据库·redis
KAI_KD4 小时前
自定义JackSon配置
java
运维@小兵4 小时前
SpringBoot获取用户信息常见问题(密码屏蔽、驼峰命名和下划线命名的自动转换)
java·spring boot·后端
新时代苦力工5 小时前
Java实现使用EasyExcel按模板导出文件
java
小陈095 小时前
Java后端图形验证码的使用
java·开发语言·状态模式
27669582925 小时前
得物 小程序 6宫格 分析
java·python·小程序·得物·得物小程序·得物六宫格·六宫格验证码
知了一笑5 小时前
通过IP计算分析归属地
java·ip·ip定位·ip计算