asList 引发的血案

asList 引发的血案详情见如下代码 Testpublicvo Integer a 1 2 3 4 5 List lt Integer gt list Arrays asList a 尝试着向集合中再添加一个元素 list add 6 for Integert

详情见如下代码:

 @Test public void testArraysList(){ Integer[] a = { 
  1,2,3,4,5}; List 
  
    list = Arrays.asList(a); 
   //尝试着向集合中再添加一个元素。 list.add( 
   6); 
   for( Integer temp : list ) { System.out.println(temp); } } 
  

  很简单的程序啊,不过,这段程序执行会不会有什么问题呢?

  运行后,会出现如下结果:

 java.lang.UnsupportedOperationException at java.util.AbstractList.add(AbstractList.java:148) at java.util.AbstractList.add(AbstractList.java:108) 

  UnsupportedOperationException,不支持的操作。居然不支持 List 的 add 方法,真是奇怪了!还是追根寻源,看看 asList 的源码:

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

  直接 new 了一个 ArrayList ,难道 ArrayList 不支持 add 方法?不可能呀!问题就出在这个 ArrayList 上,此处的 ArrayList 并非我们熟悉的 java.util.ArrayList,而是 ArrayList 工具类中的一个内置类。

这里写图片描述

 //这是一个私有的静态内部类 private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable { 
    private static final long serialVersionUID = -0L; //存储列表元素的数组 private final E[] a; //唯一的构造器 ArrayList(E[] array) { a = Objects.requireNonNull(array); } /*其他方法省略*/ } 

  这里的 ArrayList 是一个静态私有内部类,除了 Arrays 能访问外,其他类度不能访问。仔细看这个类,发现它没有提供 add 方法,那肯定是父类 AbstractList 提供的,来看代码:

 public boolean add(E e) { add(size(), e); return true; } public void add(int index, E element) { throw new UnsupportedOperationException(); } 

  父类确实提了 add 方法,但是没有具体的实现,所以每个子类都要覆写 add 方法,而 ArrayList 没有覆写,因此 add 一个元素就会报错。

  • size:元素数量
  • toArray:转换为一个数组
  • get:获得指定元素
  • set:重置指定元素
  • indexOf:返回指定元素的索引下标
  • contains:是否包含某元素
  • sort:排序

      对于我们经常使用的 List.add 和 List.remove() 方法,都没有实现,也就是说, asList 返回的是一个长度不可变的列表,数组是多长,转换的列表也就是多长,不再保持列表动态边长的特性。
      

      虽然 Arrays.asList 用起便捷,但是却深藏着重大隐患 —— 列表长度无法修改切记千万不要把这样的 List 对象传递到一个允许 add 操作的方法中

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/225145.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 上午10:00
下一篇 2026年3月17日 上午10:00


相关推荐

  • Git 工具 – 高级合并「建议收藏」

    高级合并在Git中合并是相当容易的。因为Git使多次合并另一个分支变得很容易,这意味着你可以有一个始终保持最新的长期分支,经常解决小的冲突,比在一系列提交后解决一个巨大的冲突要好。然而,有时也会有棘手的冲突。不像其他的版本控制系统,Git并不会尝试过于聪明的合并冲突解决方案。Git的哲学是聪明地决定无歧义的合并方案,但是如果有冲突,它不会尝试智能地自动解决它。因此,如果很久之后才合并两个分叉的分支,你可能会撞上一些问题。在本节中,我们将会仔细查看那些问题是什么以及Git

    2022年4月6日
    76
  • GoLand 2022.01.21 激活码_在线激活2022.02.01「建议收藏」

    (GoLand 2022.01.21 激活码)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~CJM5ZJBPHS-eyJsaWNlbnNlSWQiOi…

    2022年3月31日
    83
  • adb命令修改手机分辨率_adb命令查看安卓版本

    adb命令修改手机分辨率_adb命令查看安卓版本打开所要查看的应用包名:$adbshelldumpsysactivitytop|head-n10TASKcom.ss.android.article.newsid=5ACTIVITYcom.ss.android.article.news/com.ss.android.article.base.activity.DetailActivity4407b468pid=2714…

    2022年8月13日
    3
  • 序列化和反序列化的底层实现原理是什么?

    序列化和反序列化的底层实现原理是什么?序列化和反序列化作为Java里一个较为基础的知识点,大家心里也有那么几句要说的,但我相信很多小伙伴掌握的也就是那么几句而已,如果再深究问一下Java如何实现序列化和反序列化的,就可能不知所措了!遥记当年也被问了这一个问题,自信满满的说了一大堆,什么是序列化、什么是反序列化、什么场景的时候才会用到等,然后面试官说:那你能说一下序列化和反序列化底层是如何实现的吗?一脸懵逼,然后回家等通知!一、…

    2022年6月15日
    28
  • 初识SQL Server2017 图数据库(一)

    初识SQL Server2017 图数据库(一)

    2021年11月24日
    41
  • OSChina 周六乱弹 —— 人家过得是造儿童节,咱呢?[通俗易懂]

    2019独角兽企业重金招聘Python工程师标准>>>…

    2022年4月9日
    45

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号