Arrays.asList() 都有什么隐藏的陷阱?
👉 这是一个或许对你有用的社群
🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料:
《项目实战(视频)》:从书中学,往事上“练” 《互联网高频面试题》:面朝简历学习,春暖花开 《架构 x 系统设计》:摧枯拉朽,掌控面试高频场景题 《精进 Java 学习指南》:系统学习,互联网主流技术栈 《必读 Java 源码专栏》:知其然,知其所以然
👉这是一个或许对你有用的开源项目
国产 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 双版本
Arrays.asList()
方法我们平时开发中一定经常使用,它是将数组转换为List的一种便捷方式,但它有一些潜在的陷阱需要注意。使用的时候需要多多注意呦。
1.不可变性
Arrays.asList()
返回的List是固定大小的,这意味着它不支持对元素的增删操作。任何试图修改大小的操作都会导致UnsupportedOperationException
。
因为它返回的是 java.util.Arrays.ArrayList
的实例,而不是 java.util.ArrayList
。Arrays.ArrayList
是一个内部类,它基于一个固定大小的数组,并将其包装为 List
接口的实现。因此,它不支持添加或删除元素,只能对现有元素进行修改。
源码贴张图吧,能看到size属性是按照入参的长度给定的:
示例
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
// 创建一个固定大小的List
List<String> list = Arrays.asList("a", "b", "c");
// 尝试添加元素
// list.add("d"); // 这会抛出 UnsupportedOperationException
// 尝试删除元素
// list.remove(0); // 这会抛出 UnsupportedOperationException
// 尝试清空列表
// list.clear(); // 这会抛出 UnsupportedOperationException
// 可以修改现有元素
list.set(0, "A");
System.out.println(list); // 输出 [A, b, c]
}
}
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/ruoyi-vue-pro 视频教程:https://doc.iocoder.cn/video/
2.返回的是java.util.Arrays$ArrayList
返回的列表是 java.util.Arrays
的一个私有静态类,而不是标准的 ArrayList
类。这意味着一些 ArrayList
的方法和特性可能不可用。
Arrays.asList()
返回的 ArrayList
和真正的 ArrayList
在某些方面是相似的,但也有一些重要的区别。
相似之处:
「元素访问」 :两者都支持通过索引访问元素。 「迭代」 :可以使用迭代器或增强型 for 循环来遍历它们。 「尺寸」 :都具有 size()
方法来获取列表的大小。
区别:
1.可修改性 :
Arrays.asList()
返回的列表是固定大小的,不能添加或删除元素,也不能调整大小。真正的 ArrayList
具有添加、删除和调整大小的方法,因此它是可修改的。
2.添加/删除元素方法 :
Arrays.asList()
返回的列表不支持添加或删除元素的方法(例如add()
、remove()
等),尝试调用这些方法将会抛出UnsupportedOperationException
异常。真正的 ArrayList
具有添加、删除和替换元素的方法。
3.修改元素 :
Arrays.asList()
返回的列表允许修改元素,但不允许改变列表的大小。真正的 ArrayList
则允许修改元素,并且也可以添加或删除元素。
4.toArray() 方法 :
Arrays.asList()
返回的列表的toArray()
方法返回的数组是底层数组的视图,对该数组的修改将反映在列表中。真正的 ArrayList
的toArray()
方法则返回一个全新的数组副本,对该数组的修改不会影响到列表。
5.clear() 方法 :
真正的 ArrayList
有一个clear()
方法,用于清空列表中的所有元素,而Arrays.asList()
返回的列表不支持此方法。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/yudao-cloud 视频教程:https://doc.iocoder.cn/video/
3.数组元素类型必须是引用类型
Arrays.asList()
方法的参数是可变参数(varargs),并且泛型参数类型被推断为数组的类型。因此,如果传递的是基本数据类型的数组,它将被看作是一个对象,而不是数组。因为它的签名是 asList(T... a)
,其中 T
是泛型类型。这意味着我们可以传递零个或多个参数给这个方法,而不需要显式地创建一个数组来传递。
❝
对于参数类型的推断,Java 中的自动装箱和拆箱会影响到这一点。自动装箱是指基本数据类型可以自动转换为对应的包装类型,而自动拆箱则是指包装类型可以自动转换为基本数据类型。因此,如果传递的是基本数据类型的数组,Java 会将其自动装箱为对应的包装类型的数组。
❞
这也是为什么如果传递的是基本数据类型的数组,它将被看作是一个对象,而不是数组。这里的数组实际上是对象数组,而不是基本数据类型的数组。
示例:
int[] array = {1, 2, 3};
List<int[]> list = Arrays.asList(array); // 注意这里的泛型参数是 int[]
System.out.println(list.size()); // 输出 1,因为传递了一个对象,即整个数组作为一个元素
相反,如果传递的是包装类型的数组,它将会被识别为数组的数组元素:
Integer[] array = {1, 2, 3};
List<Integer> list = Arrays.asList(array); // 注意这里的泛型参数是 Integer
System.out.println(list.size()); // 输出 3,因为传递了三个元素,即数组的每个元素都是列表的一个元素
4.数组内容修改影响List
因为Arrays.asList()
返回的List是基于原始数组的,如果对原始数组进行修改,会影响到返回的List,反之亦然。
示例:
String[] array = {"one", "two", "three"};
List<String> list = Arrays.asList(array);
System.out.println(list);//输出 [one, two, three]
array[0] = "four";
System.out.println(list); // 输出 [four, two, three]
list.set(1, "five");
System.out.println(Arrays.toString(array)); // 输出 [four, five, three]
5.使用ArrayList构造新的可变List
如果需要一个可变的List,最好使用new ArrayList<>(Arrays.asList(array))
,这样就可以避免固定大小和不可变性的问题。
示例:
String[] array = {"one", "two", "three"};
List<String> list = new ArrayList<>(Arrays.asList(array));
list.add("four"); // 不会抛出 UnsupportedOperationException
总体而言,使用Arrays.asList()
时,要注意其返回的List的特性,以避免潜在的问题。在需要可变性、对List进行增删操作或处理包含null元素的数组时,建议使用new ArrayList<>(Arrays.asList(array))
等方式。
欢迎加入我的知识星球,全面提升技术能力。
👉 加入方式,“长按”或“扫描”下方二维码噢:
星球的内容包括:项目实战、面试招聘、源码解析、学习路线。
文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
微信扫码关注该文公众号作者