详讲Arrays.asList()方法,可别再踩坑

Arrays

Arrays 是数组对象进行操作的工具类,其中含有对数组的排序、查找、对比、拷贝等操作。通过工具类,我们还可以将数组转换成集合。

​数组和集合都是 Java 中用来存储数据的,数组性质单一,方便使用;集合通过泛型达到类型安全,功能强大,而且两者之间还可以进行互相转换。毕竟两者之间有明显不同,在进行转换的时候,如果稍不注意就会出错。

转换时分为两种情况:

  • 数组转换成集合
  • 集合转换成数组

错误:java.lang.UnsupportedOperationException

举个平时容易遇错的问题:将数组转换成集合是用Arrays.asList()方法。转换后的集合,如果要使用 add/remove/clear ,那么会抛出java.lang.UnsupportedOperationException 异常。

	String[] strings = {"ab","cd","ef"};
	List<String> list = Arrays.asList(strings);

	// 三行语句都编译通过,但都抛出运行时异常
	list.add("gh");
	list.remove("cd");
	list.clear();
	// set修改成功,将第一位改成"aa"
	list.set(0,"aa");
	
	// 遍历出做对比
	for (String string : strings) {
    	System.out.print(string + ",");
	}
	System.out.println();
	System.out.println(list);

运行结果为:

// 发现原数组也别修改了
aa,cd,ef,
[aa, cd, ef]

​通过上段代码可以发现,我们可以使用 set 方法,而且不会抛出运行时异常,在修改集合List中值的同时,原数组上的值也跟着被修改了。因为Arrays.asList()采用的是适配器模式,在后台操作的数据仍是原有的数据,set方法也就是间接对数组里的值进行修改。返回值为修改前的旧值。

另外还发现,只要是修改元素个数的操作,就会抛出java.lang.UnsupportedOperationException异常。

查看源码

​我们再进一步了解 asList 方法它具体返回的到底什么对象,进入源码查看:

public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}

​从源码中可发现,它返回的是一个 ArrayList 对象。

那为什么它不能像ArrayList那样正常的对数据操作?继续点下去:
在这里插入图片描述
惊人的发现,原来在 Arryas 中竟然定义了一个 ArrayList 的内部类,它与平时 Arrays 同包下的 ArrayList 并不是同一个类!难怪会有功能限制。

简单的翻了下不到100行的内部类源码,除了有看到了 set 修改方法外,却怎么也找不到能修改集合个数的相关方法,那么是谁抛出了java.lang.UnsupportedOperationException 异常?答案是内部类的父类 AbstractList。

源码:(注解太长了,就不截图了)摘取关键源码

public abstract class AbstractList<E> extends AbstractCollection<E> 
	implements List<E> {
	
	public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
    
 	public E remove(int index) {
        throw new UnsupportedOperationException();
    }   
    // clear()方法在内部转了一圈还是调用remove方法,依然抛出
    public void clear() {
        removeRange(0, size());
    }

所以在业务上,如果以这样的方式返回一个 List,即使在大部分情况下都只做读操作,但只要有一个写入修改操作,那么就会出错引发故障。

解决问题

当然,这也不是没有解决的办法,可以将Arrays.asList()返回的 List 作为参数创建一个新的 ArrayList。

String[] strings = {"ab","cd","ef"};
List<String> list = new ArrayList<>(Arrays.asList(strings));

这样一来,就可以正常使用了。在这里插入图片描述
愿世上永无Bug

猜你喜欢

转载自blog.csdn.net/PINKMIAO/article/details/108411314