调用ArrayList的add方法抛异常UnsupportedOperationException

对于一些想要把数组转成List的需求,可能会使用到Arrays.asList()获取List对象,但是这里面也存在一些问题。

示例代码如下

    void test1(){
List<Object> list = Arrays.asList();
list.add("hello");
}

执行后报错信息为

java.lang.UnsupportedOperationException
at java.base/java.util.AbstractList.add(AbstractList.java:153)
at java.base/java.util.AbstractList.add(AbstractList.java:111)
at com.heima.item.test.test.test1(test.java:15)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
......

在上述代码中,list.add("hello")执行报错,异常为java.lang.UnsupportedOperationException,通过查看Arrays里的asList()方法可以看到如下信息

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

这边是new了一个新的ArrayList对象,有人可能以为这是我们所熟悉的那个ArrayList,但是其实不是,这是【java.util.Arrays.ArrayList】,而我们常用的ArrayList是【java.util.ArrayList】在Arrays的源码里面可以看到压根没有导入我们熟悉的那个ArrayList,而是定义了一个内部类。简单来说这是两个类,只是名字相同了,恰好都是ArrayList

这个内部类是直接继承了AbstractList,它并没有重写add方法,所以我们调了add方法其实是调的AbstractList里的add方法,AbstractList里的add方法源码为

    public void add(int index, E element) {
throw new UnsupportedOperationException();
}

原因很明显,不重写的话一调就抛出异常UnsupportedOperationException。

不止add方法,set,remove这些方法也不能通过Arrays.asList得到的对象调用,具体可以参考Arrays和AbstractList这两个类的源码。

另辟蹊径:

方法一

对于想要通过asList来获取List对象,又想调用add方法的,可以使用下列方式得到java.util.ArrayList对象,没错这正是我们常用的List实例对象。

    void test2(){
String [] strs = {"AAA", "BBB", "CCC"};
List<String> list1 = Arrays.asList(strs); ArrayList<String> list2 = new ArrayList(list1);
list2.add("XXX"); list2.forEach(System.out::println);
}

通过这种方式,可以正常add元素进入list,遍历打印出来的结果如下

AAA
BBB
CCC
XXX

方法二

避免使用Arrays.asList,而是使用Collections.addAll来帮助我们把数组里的元素全部添加到List对象里。

    void test3(){
String [] strs = {"AAA", "BBB", "CCC"};
List<String> list1 = Arrays.asList(strs); ArrayList<String> list2 = new ArrayList<>();
Collections.addAll(list2, strs); list2.add("YYY");
list2.forEach(System.out::println);
}

遍历打印出来的结果如下

AAA
BBB
CCC
YYY

方法三

遍历复制元素。把java.util.Arrays.ArrayList里的元素遍历,然后一个个添加进入自己创建的java.util.ArrayList实例里。

    void test4(){
String [] strs = {"AAA", "BBB", "CCC"};
List<String> list1 = Arrays.asList(strs); ArrayList<String> list2 = new ArrayList<>(); list1.forEach(e -> {
list2.add(e);
}); list2.add("ZZZ");
list2.forEach(System.out::println);
}

遍历打印出来的结果如下

AAA
BBB
CCC
ZZZ

方法四

遍历复制元素。把java.util.Arrays.ArrayList里的所有元素一次性添加进入自己创建的java.util.ArrayList实例里。

    void test5(){
String [] strs = {"AAA", "BBB", "CCC"};
List<String> list1 = Arrays.asList(strs); ArrayList<String> list2 = new ArrayList<>();
list2.addAll(list1); list2.add("OOO");
list2.forEach(System.out::println);
}

遍历打印出来的结果如下

AAA
BBB
CCC
OOO

方法五

直接创建java.util.ArrayList对象,使用for循环遍历数组然后add元素。

其他方法

还有一些没有介绍到的方式,比如List.copyOf,Stream API之类等等,最后都能得到想要的对象,但是不够简单。比较推荐使用常见的这几种方式。

调用ArrayList的add方法抛异常UnsupportedOperationException的更多相关文章

  1. ArrayList的add方法实现

    ArrayList的底层是由数组实现,所以所有的操作都是围绕数组展开,要想理解add方法,就得先了解数组的增加,所以我们先实现一个数组的add,数组的添加可以从尾部增加或者其他位置插入, 如果在数组的 ...

  2. CloudStack的VO在调用setRemoved方法抛异常的原因

    今天在开发中发现一个问题,本来想对一个VO对象的removed值赋值,然后去update一下这条记录,一个最简单的set方法,但是在调用时直接抛异常了. 1: public void setRemov ...

  3. ABP在领域事件中异步调用方法抛异常

    在领域事件中调用UserRegistrationManager.RegisterAsync抛异常 Call UserRegistrationManager.RegisterAsync() throw ...

  4. 执行ArrayList的remove(object)方法抛异常?

    简介 或许有很多小伙伴都尝试过如下的代码: ArrayList<Object> list = ...; for (Object object : list) { if (条件成立) { l ...

  5. 【Java】ArrayList 的 toArray() 方法抛出 ClassCastException 异常

    第一次用这个方法,结果冒出个莫名其妙的异常来: String[] names = (String[]) mTags.toArray(); 结果会抛出 java.lang.ClassCastExcept ...

  6. 关于ArrayList add()方法 中的引用问题

    ArrayList的add方法每次添加一个对象时,添加 的是一个对象的引用,比如进行循环操作10次  lists.add(a) 每次 a会改变 ,这时候你会发现你在lists里添加了10个相同的对象a ...

  7. 抛异常 throw的注意事项

    子类覆盖父类只能抛出父类的异常或者子类或者子集注意:如果父类的方法没有抛异常,那么子类覆盖时绝对不能抛. 子类继承父类时,方法抛异常,要么抛父类,要么抛父类下的子类,不能抛父类平级或以上的异常 原因是 ...

  8. 【java】子类可以通过调用父类的public方法调用父类的private方法,为什么?

    代码1: 打印结果: 代码2: 运行结果: 问题: 代码1中super是父类自己调用自己的add()方法,并在add()方法中调用了私有的del()方法,那为什么打印出来的this是子类? 代码2中t ...

  9. ArrayList调用remove(int index)抛出UnsupportedOperationException问题分析以及解决记录

    使用Arrays转数组成为List后,不能调用add(...)和remove(...)方法,此时如果调用就会抛出UnsupportedOperationException异常 原因 其实Arrays. ...

  10. 浅析调用JSR303的validate方法, 验证失败时抛出ConstraintViolationException

    废话不多说,直接进入正题:如何使用JSR303的validate,进行数据校验,失败后直接抛出异常加入流转信息中,并在form页面提示出来. 首先我们为了启用验证,需要向 项目中添加Bean验证的实现 ...

随机推荐

  1. Django生成数据库表时报错 __init__() missing 1 required positional argument: 'on_delete'

    原因: 在django2.0后,定义外键和一对一关系的时候需要加上on_delete选项,此参数为了避免两个表里的数据不一致问题,不然会报错 例如: owner=models.ForeignKey(U ...

  2. 面试官:Java对象引用都有哪些类型?

    哈喽,大家好,我是世杰. 本文我为大家介绍面试官经常考察的「Java对象引用相关内容」 照例在开头留一些面试考察内容~~ 面试连环call Java对象引用都有哪些类型? Java参数传递是值传递还是 ...

  3. SQL注入漏洞攻击

    l-> 对于用户登录的实现,提供SQL语句 •-> select * from 表名 where uid=- and pwd=- •-> 使用字符串拼接 l-> 提供密码为:' ...

  4. 效率工具RunFlow完全手册之进阶篇

    欢迎来到RunFlow手册的进阶篇,如果您还不了解RunFlow,建议先阅读我们的基础篇. (Solo 社区投稿) 搜索文件 按文件大小过滤,添加 len 参数,比如:len:1kb-2kb,len: ...

  5. Django __init__ 方法用于初始化

    使用面向对象的方法来创建一个栈板信息的模型,比如使用 Python 的类来表示栈板信息.以下是一个简单的示例: class Pallet: def __init__(self, number, nam ...

  6. C# ClassHelper动态创建程序集和类, 添加/删除类属性

    using System; using System.Collections.Generic; using System.Reflection; using System.Reflection.Emi ...

  7. Python 按规则解析并替换字符串中的变量及函数

    按规则解析并替换字符串中的变量及函数 需求 1.按照一定规则解析字符串中的函数.变量表达式,并替换这些表达式.这些函数表达式可能包含其它函数表达式,即支持函数嵌套 2.函数表达式格式:${ __函数名 ...

  8. CCF 命令行选项

    题目原文 问题描述(题目链接登陆账号有问题,要从这个链接登陆,然后点击"模拟考试",进去找本题目)   试题编号: 201403-3 试题名称: 命令行选项 时间限制: 1.0s ...

  9. NPIO在指定位置插入新列(附案例和代码)

    背景: I could be mistaken as I am not that familiar with NPOI, however, after a minor search, it appea ...

  10. MySQL常用语句(经常容易忘记)

    MySQL常用语句 一.连接MySQL 格式: mysql -h <主机地址> -u<用户名> -p<用户密码> --port=<端口号> 1.例1:连 ...