⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 飞天小牛肉 「小牛肉」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

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:

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

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

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

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

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

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

第二个坑

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

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

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

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

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

第三个坑

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

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

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

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

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

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

文章目录
  1. 1. 第一个坑
  2. 2. 第二个坑
  3. 3. 第三个坑