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交流群,欢迎大家加入,过期加我拉你们进哈!

相关推荐
工藤学编程几秒前
分库分表之实战-sharding-JDBC水平分库+分表后:查询与删除操作实战
数据库·spring boot·后端·sql·mysql
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ1 分钟前
如何将一个本地的jar包安装到 Maven 仓库中
java·maven·jar
N维世界10 分钟前
Mybatis-XML映射文件
xml·java·mybatis
码出极致12 分钟前
Redisson 分布式锁自动续期机制解析
后端
小塵13 分钟前
【DeepSeek 聊天】五分钟部署本地 DeepSeek
人工智能·后端·deepseek
土拨鼠的旅程15 分钟前
Go map 源码详解【2】—— map 插入
后端
泊浮目18 分钟前
生产级Rust代码品鉴(一)RisingWave一条SQL到运行的流程
大数据·后端·rust
弹简特32 分钟前
【Java SE】Arrays工具类
java·开发语言
Touper.33 分钟前
JavaSE -- Lambda表达式
java·开发语言
estarlee36 分钟前
通用图片搜索-搜狗源免费API接口使用指南
后端