山东建设局网站电工,网站打开速度概念,wordpress取消更改,网络下载的网站模板能直接上传到虚拟主机一、前言
在 Java 开发中#xff0c;Arrays.asList() 是一个常用的工具方法#xff0c;它允许开发者快速将数组转换为列表。尽管这个方法非常方便#xff0c;但许多开发者在使用时可能会遭遇一个常见的错误#xff1a;尝试向由 Arrays.asList() 返回的列表中添加元素时抛出…一、前言
在 Java 开发中Arrays.asList() 是一个常用的工具方法它允许开发者快速将数组转换为列表。尽管这个方法非常方便但许多开发者在使用时可能会遭遇一个常见的错误尝试向由 Arrays.asList() 返回的列表中添加元素时抛出异常。本文将详细探讨这个现象的根本原因并提供相关的使用示例和解决方案。。
二、事故回顾
这个问题是出现开发一个电商平台的订单系统时遇到了类似的问题。需要将一个订单ID数组转换为一个List并在后续的业务逻辑中向这个List中添加新的订单ID。
由于小伙伴经验不足使用了Arrays.asList()方法部署到线上导致在添加新订单ID时抛出了UnsupportedOperationException异常整个订单处理流程中断线上系统出现了严重的故障。
影响分析
这次事故对电商平台造成了巨大的影响
用户体验下降 由于订单处理流程中断用户无法正常下单导致用户体验大幅下降。业务中断 订单系统的故障直接影响到了整个电商平台的业务运营造成了大量的订单积压。经济损失 由于业务中断平台失去了大量的潜在收入给公司带来了不小的经济损失。信任危机 频繁的系统故障让用户对平台的信任度下降可能导致用户流失。
后面也是及时修复吸取本次事故教训。
三、事故问题描述
1、首先先简单描述一下这个事故问题废话不多说直接看实际业务代码也就将一个数组转换为List并对这个List进行增删操作。
Integer[] arr {1, 2};ListInteger list Arrays.asList(arr);list.add(3);
上述代码看起来没问题编译器也没有报错。但是运行这段代码时会抛出UnsupportedOperationException异常提示我们不支持添加操作。这究竟是怎么回事呢 所以这是不是个大坑如果在实际开发中没有进行自测必定不会酿成重大线上事故。
四、问题分析
上述已经知道这个使用Arrays.asList()将数组装换成List会在add情况会报错接下来深入源码进行分析。
Arrays.asList()的内部实现
Arrays.asList(arr)方法实际上返回的是一个Arrays类的内部类ArrayList而不是我们常用的java.util.ArrayList。这个内部类ArrayList继承自AbstractList并没有实现add和remove方法。 Arrays类的内部类ArrayList完整源码如下
private static class ArrayListE extends AbstractListEimplements RandomAccess, java.io.Serializable
{private static final long serialVersionUID -2764017481108945198L;private final E[] a;ArrayList(E[] array) {a Objects.requireNonNull(array);}Overridepublic int size() {return a.length;}Overridepublic Object[] toArray() {return a.clone();}OverrideSuppressWarnings(unchecked)public T T[] toArray(T[] a) {int size size();if (a.length size)return Arrays.copyOf(this.a, size,(Class? extends T[]) a.getClass());System.arraycopy(this.a, 0, a, 0, size);if (a.length size)a[size] null;return a;}Overridepublic E get(int index) {return a[index];}Overridepublic E set(int index, E element) {E oldValue a[index];a[index] element;return oldValue;}Overridepublic int indexOf(Object o) {E[] a this.a;if (o null) {for (int i 0; i a.length; i)if (a[i] null)return i;} else {for (int i 0; i a.length; i)if (o.equals(a[i]))return i;}return -1;}Overridepublic boolean contains(Object o) {return indexOf(o) ! -1;}Overridepublic SpliteratorE spliterator() {return Spliterators.spliterator(a, Spliterator.ORDERED);}Overridepublic void forEach(Consumer? super E action) {Objects.requireNonNull(action);for (E e : a) {action.accept(e);}}Overridepublic void replaceAll(UnaryOperatorE operator) {Objects.requireNonNull(operator);E[] a this.a;for (int i 0; i a.length; i) {a[i] operator.apply(a[i]);}}Overridepublic void sort(Comparator? super E c) {Arrays.sort(a, c);}
}
可以看到并没有实现add和remove方法这两个方法在父类中默认抛出UnsupportedOperationException异常。 具体原因
下面是内部源码的分析
1.内部类ArrayList的限制
Arrays.asList(arr)返回的内部类ArrayList是一个固定长度的列表它没有实现add和remove方法。
当我们调用list.add(3)时实际上调用的是AbstractList中的add方法而这个方法直接抛出了UnsupportedOperationException异常。
2.源码分析
AbstractList的add方法如下 五、解决方案
面对这一限制开发者可以采取以下几种方式来处理 Arrays.asList() 返回的列表
1、使用 new ArrayList() 创建可变列表
如果需要一个可变大小的列表可以使用 new ArrayList(Arrays.asList(fruits)) 进行转换 这种方式创建了一个新的 ArrayList 实例它的大小是可变的因此可以自由添加、删除元素。
ListString dynamicList new ArrayList(Arrays.asList(Apple, Banana, Cherry));dynamicList.add(Date); // 现在可以成功添加元素System.out.println(dynamicList);
2、直接初始化 ArrayList
另一种选择是直接使用 ArrayList 的构造函数并传入数组元素 这种方法提供了更大的灵活性适合需要动态修改的场景。
ListString dynamicList new ArrayList();Collections.addAll(dynamicList, Apple, Banana, Cherry);dynamicList.add(Date); // 添加成功
3、使用流Streams
在 Java 8 及更高版本中可以利用流的 API 来创建可变列表 这种方法简洁而现代化适合喜欢函数式编程风格的开发者。
ListString dynamicList Stream.of(Apple, Banana, Cherry).collect(Collectors.toList());dynamicList.add(Date); // 添加成功
转载小哈学Java