全是坑!慎用 Arrays.asList...

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料: 

b0a4614067cc34c75eb370892dd3c272.gif

👉这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号、CRM 等等功能:

  • Boot 仓库:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • Cloud 仓库:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn

【国内首批】支持 JDK 21 + SpringBoot 3.2.2、JDK 8 + Spring Boot 2.7.18 双版本 

来源:飞天小牛肉


Java 8 提供的 Stream 流式处理大大减少了集合类各种操作(投影、过滤、转换)的代码量,用起来非常香,所以在实际业务开发中,我们常常会把原始的数组转换为 List 类数据结构,使得其可以用上 Stream 流操作。

Arrays.asList 方法应该是各位最常用的数组一键转换为 List 的方法了,但这个方法有几个坑,如果不了解的话,排查 Bug 可能会比较困难:

  1. 坑 1:不能直接使用 Arrays.asList 来转换基本类型数组

  2. 坑 2:Arrays.asList 返回的 List 不支持增删操作

  3. 坑 3:对原始数组的修改会影响 Arras.asList 返回的那个 List

第一个坑

在如下代码中,我们初始化三个数字的 int[]数组,然后使用 Arrays.asList 把数组转换为 List:

74eea45d2294cce09083634b62041b5c.png

但,这样初始化的 List 并不是我们期望的包含 3 个数字的 List,输出结果如下:

a0a14b0f8f287cd09b780a329723dcfb.png

可以发现,这个 List 包含的其实是一个 int 数组,整个 List 的元素个数是 1,元素类型是整数数组

其原因是,只能是把单个 int 类型装箱为 Integer,不能把 int 数组装箱为 Integer 数组 。Arrays.asList 方法传入的是一个泛型 T 类型可变参数,所以 int 数组实际上是被整体看成一个对象作为泛型类型 T:

c0f2bb512df7064626199654ca4596ed.png

以上,就是第一个坑:不能直接使用 Arrays.asList 来转换基本类型数组。直接遍历这样的 List 必然会出现 Bug,修复方式有两种:

  1. 最简单的,直接把数组声明为包装类型,不要用 int 这种基本类型

729734a646909044600500416426d3e3.png
  1. 如果使用 Java8 以上版本可以使用 Arrays.stream 方法来转换,stream 流提供了 boxed 装箱操作:

a1f417c8f9f3665cddc271f0cc77ea68.png

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

第二个坑

把三个字符串 1、2、3 构成的字符串数组,使用 Arrays.asList 转换为 List 后,然后为 List 增加一个字符串 4:

1f9e7f88e734392e41382cda4b7f1f91.png

结果如下,为 List 新增字符串 4 的操作失败了,报错  UnsupportedOperationException

62f87c9551a934438ce0c33f40e0d2a5.png

第二个坑:Arrays.asList 返回的 List 不支持增删操作

因为 Arrays.asList 返回的 List 并不是我们期望的 java.util.ArrayList,而是 Arrays 的内部类 ArrayList:

2c171e452eb664227b72d75c4773979f.png

ArrayList 内部类继承自 AbstractList 类,并没有覆写父类的 add 方法,而父类中 add 方法的实现,就是抛出 UnsupportedOperationException

2f51e2c566045f1b5158ca8ac9cd0e51.png

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

第三个坑

把三个字符串 1、2、3 构成的字符串数组,使用 Arrays.asList 转换为 List 后,然后修改原字符串数组的第一个元素为 0:

f04d087f5fef7b5a6378cab54e1bc48e.png

输出如下,把原始数组的第一个元素从 1 修改为 0 后,asList 获得的 List 中的第一个元素也被修改为 0 了:

4c2adb2fc7bf77d48d96cf8f2e0bc8ab.png

第三个坑:对原始数组的修改会影响 Arras.asList 返回的那个 List

看一下 ArrayList 的实现,可以发现 ArrayList 其实是直接使用了原始的数组 。所以,我们要特别小心,把通过 Arrays.asList 获得的 List 交给其他方法处理,很容易因为共享数组,相互修改而产生 Bug。

350164eba9346bec571a51a1eb30009b.png

第二个坑和第三个坑的本质原因是一样的,都是由于数组共享导致的问题,所以解决方式比较简单,重新 new 一个 ArrayList 初始化 Arrays.asList 返回的 List 即可:

c7022889bc33fea599a889d2c2f92eea.png

修改后的代码实现了原始数组和 List 的解耦,不再相互影响。同时,因为操作的是真正的 ArrayList,add 也不再报错:

7c48c8a7f56885b26aada94e6aef7043.png

欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,长按”或“扫描”下方二维码噢

5e60cd493d45859857255e0306431fb9.png

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

3141f7df0721a11fc8870afe65d4da1b.png

39a0713b656c5426b8e83adad4b9de4d.png37f76f22ddaf4badb6eb40cc5746f36c.pngdf66b82b8f4a5c7ef033de5cf72f4e54.png090bf07335db0ed179c5ed56cccb5e64.png

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值