• Arrays.asList()你真的知道怎么用吗?


    发现问题

    前几天在看别人的项目的时候,发现一个问题,简单复现一下这个问题

    // 注意这是一个Integer对象的数组哦
    Integer[] arr = new Integer[]{9999,88,77};
    List list = Arrays.asList(arr);
    // 执行以下操作,有问题么?
    list.add(1);
    list.remove(0);
    

    好的,如果你觉得没错,和我刚开始的想法一致。在我没有认真学习这个asList方法时,天真的以为没有问题,顾名思义啊,就是把数组转换成List呗。

    // 恭喜,喜提报错,如果是这样测试该找你麻烦了,/(ㄒoㄒ)/~~ 
    Exception in thread "main" java.lang.UnsupportedOperationException
    	at java.util.AbstractList.add(AbstractList.java:148)
    	at java.util.AbstractList.add(AbstractList.java:108)
    	at TestForAsList.main(TestForAsList.java:13)
    

    废话不多说,我们直接进源码里面看看。

    @SafeVarargs
    @SuppressWarnings("varargs")
    public static  List asList(T... a) {
        return new ArrayList<>(a);  // 看起来没有任何异常,emm。然而呢,这个ArrayList并不是Java.util包下的ArrayList,而是一个在Arrays下实现的内部类。
    }
    

    image

    我们发现这个静态内部类里面并没有实现List的add和remove方法。那么子类将延用父类AbstractList的方法实现,这个继承应没有什么问题。

    // 我们进入这个父类的实现,发现了报错的根源。。
    public abstract class AbstractList extends AbstractCollection implements List {
        
    	public void add(int index, E element) {
            throw new UnsupportedOperationException();
        }
    
    
        public E remove(int index) {
            throw new UnsupportedOperationException();
        }
    }
    

    总结:

    究其原因,就是这个asList方法返回的是一个内部类,只实现了一些遍历以及更新的方法。下次使用它的时候需要注意一下。

    扩展知识点

    数组值的变化

    然后我就发现了这个很有意思的点,就是这个Arrays包下的ArrayList用的是构造器传进来的数组,并不像我们原来认为的ArrayList的那样会拷贝数组然后创建一个新的数组。

    这意味着我们在对这个List进行set的改动时,我们同时会更改原数组的值

    public static void main(String[] args) {
            Integer[] arr = new Integer[]{9999,88,77};
            List list = Arrays.asList(arr);
            
            list.set(1,0);
            System.out.println(list.get(1));  // 输出0
            System.out.println(arr[1]);  // 同样也输出了0
    }
    

    int[]数组

    我们都知道int是基本数据类型,如果我们向asList()方法里面传入一个int[]数组会发生什么呢?

    我们知道泛型的话需要的是对象类型,基础数据类型是不能作为泛型的。

    // 此时int[]会作为一个对象类型,然后转换为list。此时长度为1,且可以正常的取出来作为list元素
    public static void main(String[] args) {
            int[] arr = new int[]{9999,88,77};
            List<int[]> list = Arrays.asList(arr);
            System.out.println(list.size());
            System.out.println(list.get(0)[0]);
            System.out.println(list.get(0)[1]);
            System.out.println(list.get(0)[2]);
    }
    

    好了,asList()方法就学废了。一天学废一个小知识/dog


    __EOF__

  • 本文作者: captain
  • 本文链接: https://www.cnblogs.com/duizhangz/p/16660118.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    Spring实现CAS登录
    基于Java的医院住院管理系统设计与实现(源码+lw+部署文档+讲解等)
    Linux:无锁化编程 __sync_fetch_and_add原理及其实现分析
    JVM垃圾回收
    Linux本地部署1Panel现代化运维管理面板并实现公网访问
    Centos切换yum源
    全志R128芯片应用开发案例——驱动 WS2812 流水灯
    操作教程丨MaxKB+Ollama:快速构建基于大语言模型的本地知识库问答系统
    JMeter压测如何分配业务比例?
    【发布】DDD 工程脚手架 + 一键安装分布式技术栈环境!
  • 原文地址:https://www.cnblogs.com/duizhangz/p/16660118.html