刨析Arrays.asList(),用就是埋坑?
创始人
2025-05-30 07:51:36
0次

文章目录

    • 9.1 基本数据类型数组转化为List
    • 9.2 数组转换为集合后进行增删操作
    • 9.3 数组转化为集合后的数据异常
    • 9.4 数组如何真正意义转化为ArrayList集合

首先Arrays.asList()可不简单,得少用,是这道题让我深入认识这个函数,来看看输出结果?

public static void main(String[] args) {Integer[] datas = {1,2,3,4,5};List list = Arrays.asList(datas);list.add(5);System.out.println(list.size());
}

结果:运行异常,不允许添加元素。要是答错了,下面的知识可得看看了!!程序员的素养课来啦!


Arrays.asList() 作用是将数组转化为集合,但它返回的集合并非如你所愿。先来看看《阿里巴巴Java开发手册》的讲述:

使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear 方法会抛出 UnsupportedOperationException 异常。(调用的add/remove其实是AbstractList的方法,该方法就是抛出异常。后面会讲)

说明:asList 的返回对象是一个Arrays 内部类,并没有实现集合的修改方法。Arrays.asList() 体现的是适配器模式,只是转换接口,后台的数据仍是数组。

在了解以上问题前,先看看Arrays.asList()的使用吧

9.1 基本数据类型数组转化为List

int[] data = new int[]{1,2,3,4,5};
List list = Arrays.asList(data);
System.out.println(list.size());

输出结果是1,也就是说数组转化为List,是将整个数组作为一个元素!看看 Arrays.asList() 的函数如何定义就能理解了:

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

可以 asList() 看到使用了可变长泛型来定义,泛型的实例化必须是类,而基本数据类型不支持泛型化。案例中没有规定泛型,于是 asList 将数组作为泛型的实例,解决办法就是使用包装类,如下:

@Test
public void test(){Integer[] data = new Integer[]{1,2,3,4,5};List list = Arrays.asList(data);System.out.println(list.size());
}

输出结果:5

9.2 数组转换为集合后进行增删操作

public static void main(String[] args) {Integer[] datas = {1,2,3,4,5};List list = Arrays.asList(datas);list.add(5);System.out.println(list.size());
}//运行结果:抛出异常!

首先 Arrays.asList() 返回的并非是 ArrayList !自然调用 add() 等方法无法达到预期了。那为什么编译不报错,而是运行报错呢,可见此处调用其他类的方法,而非 ArrayList() 的方法!!

通过调试发现, Arrays.asList() 返回的并非是 ArrayList !(看红框框处)

image-20230318131842099

其实 Arrays.asList() 返回的是 java.util.Arrays.ArrayList,这个家伙是谁呢。看源码

public class Arrays {//省略其他方法public static  List asList(T... a) {return new ArrayList<>(a);}//hereprivate static class ArrayList extends AbstractList implements RandomAccess, java.io.Serializable{private final E[] a;ArrayList(E[] array) {a = Objects.requireNonNull(array);}@Overridepublic int size() {return a.length;}}
}

Arrays.ArrayList 是工具类 Arrays 的一个内部静态类,可以看到该内部静态类继承了 AbstractList,回到之前的题目,数组转换为集合后调用增删操作,其实调用的就是 AbstractList 中的方法,而 AbstractList 中的方法实际上是实现了List中的方法,就是抛出异常,所以**编译不报错(有方法可调),运行抛异常(方法抛异常)**看源码:

public abstract class AbstractList extends AbstractCollection implements List {//略public E set(int index, E element) {throw new UnsupportedOperationException();}public void add(int index, E element) {throw new UnsupportedOperationException();}//略
}

而 ArrayList直接实现了List 接口,实现了List所有方法,真正实现了增删等操作。

这里可以看看继承关系图。理清思路,Collection(接口)和List(接口)中定义了增删改查等操作,但没有方法体实现。AbstractList(类)实现了List中方法,也就是抛出异常,ArrayList(类)继承AbstractList(类)并实现List,对增删改查操作真正意义的实现

image-20230318134608317

总结,就是 Arrays.asList() 返回数据类型 Arrays.ArrayList而非 ArrayList

9.3 数组转化为集合后的数据异常

看看此题输出?

 @Test
public void test() {String[] arr = {"欢迎","关注","Java"};List list = Arrays.asList(arr);arr[1] = "爱上";list.set(2,"我");System.out.println(Arrays.toString(arr));System.out.println(list.toString());
}

结果:

image-20230318135132005

啊?都一样,震惊一百年啊哥们?

回到刚才的asList的源码:

//Arrays中asList
public class Arrays {//省略其他方法public static  List asList(T... a) {return new ArrayList<>(a);}//省略其他方法
}//ArrayList<>(a);
ArrayList(E[] array) {a = Objects.requireNonNull(array);
}//requireNonNull()
public static  T requireNonNull(T obj) {if (obj == null)throw new NullPointerException();return obj;
}

可以看到这是直接将数组引用返回了啊,所以数组和转化后的集合实际上公用一个数组,本质依旧数组,改了其中一个,数据都会变化。你要是不知道,数据异常的事情你是抠破脑袋也想不明白的呀!

总结asList的坑:

  1. 基本数据类型数组转化集合只有一个元素(基本数据类型不支持泛型化)
  2. 数组转化为集合,该集合不能增删改查(抛出异常,不合预期)
  3. 数据转化为集合,本质依旧是数组,公用一块空间(内部直接引用赋值)

9.4 数组如何真正意义转化为ArrayList集合

方法一:遍历添加(较low)

Integer intArray[] = {1, 2, 3};
ArrayList aList = new ArrayList<>();
for (Integer i: intArray){aList.add(i);
}

方法二:用Collections工具类中方法(addAll后面的参数为可变泛型,也就是不支持基本数据类型)

List list = new ArrayList();
Collections.addAll(list, "welcome", "to", "china");
System.out.println(list);

此法效率高?too young too simple!
addAll() 方法的实现就是用的上面遍历的方式。

方法三:将Arrays.asList返回的集合作为ArrayList的构造参数

ArrayList arrayList = new ArrayList<>(Arrays.asList("welcome", "to", "china"));

没有方法可以直接让基本数据类型的数组转化为集合,只能一个个添加,或者使用包装类。

相关内容

热门资讯

总算了解开挂!众乐乐开挂AI攻... 总算了解开挂!众乐乐开挂AI攻略,众乐乐多功能都是存在有开挂攻略1、上手简单,内置详细流程视频教学,...
程序员教你辅助!英豪娱乐城辅助... 程序员教你辅助!英豪娱乐城辅助AI工具,英豪娱乐城多功能原来真的是有辅助工具暗藏猫腻,小编详细说明英...
盘点几款辅助!冰球突破辅助AI... 盘点几款辅助!冰球突破辅助AI插件,冰球突破多功能其实真的有辅助插件1、冰球突破脚本辅助下载、冰球突...
分享一款辅助器!建湖好运麻将辅... 分享一款辅助器!建湖好运麻将辅助器AI教程,建湖好运麻将多功能竟然真的是有辅助器教程1、在建湖好运麻...
每日必备透视挂!新老夫子透视挂... 每日必备透视挂!新老夫子透视挂AI技巧,新老夫子多功能原来真的有透视挂技巧1、新老夫子脚本辅助下载、...
分享认知作弊器!星际互联作弊器... 分享认知作弊器!星际互联作弊器AI方法,星际互联多功能都是存在有作弊器方法1、每一步都需要思考,不同...
玩家必备攻略作弊器!闲逸斗地主... 玩家必备攻略作弊器!闲逸斗地主作弊器AI方法,闲逸斗地主多功能果然是有作弊器方法1、闲逸斗地主透视辅...
分辨真假透视挂!宁波游戏大厅透... 分辨真假透视挂!宁波游戏大厅透视挂AI软件,宁波游戏大厅多功能一直是有透视挂软件1、让任何用户在无需...
每日必看教程透视挂!君悦来透视... 每日必看教程透视挂!君悦来透视挂AI工具,君悦来多功能本来是有透视挂工具1、上手简单,内置详细流程视...
发现一款外挂!半岛外挂AI工具... 发现一款外挂!半岛外挂AI工具,半岛多功能一贯真的有外挂工具1、起透看视 半岛辅助软件价格2、随意选...