【Java异常】java.lang.UnsupportedOperationException解决方案

简介: 【Java异常】java.lang.UnsupportedOperationException解决方案

在最近做的一个项目中对List进行操作时报错java.lang.UnsupportedOperationException,后来发现操作的List是由数组转换而成的,通过看源码发现问题,并写测试程序如下。

代码块:

1. public class Unsupported {
2. 
3. static void test(String msg, List<String> list) {
4.         System.out.println("---- " + msg + "----");
5.         Collection<String> c = list;
6.         Collection<String> subList = list.subList(1, 8);
7. //  复制子List
8.         Collection<String> c2 = new ArrayList<>(subList);
9. try {
10.             c.retainAll(c2);
11.         } catch (Exception e) {
12.             System.out.println("retainAll()方法的异常: " + e);
13.         }
14. try {
15.             c.removeAll(c2);
16.         } catch (Exception e) {
17.             System.out.println("removeAll()方法的异常: " + e);
18.         }
19. try {
20.             c.clear();
21.         } catch (Exception e) {
22.             System.out.println("clear()方法的异常: " + e);
23.         }
24. try {
25.             c.add("X");
26.         } catch (Exception e) {
public class Unsupported {
    static void test(String msg, List<String> list) {
        System.out.println("---- " + msg + "----");
        Collection<String> c = list;
        Collection<String> subList = list.subList(1, 8);
        //  复制子List
        Collection<String> c2 = new ArrayList<>(subList);
        try {
            c.retainAll(c2);
        } catch (Exception e) {
            System.out.println("retainAll()方法的异常: " + e);
        }
        try {
            c.removeAll(c2);
        } catch (Exception e) {
            System.out.println("removeAll()方法的异常: " + e);
        }
        try {
            c.clear();
        } catch (Exception e) {
            System.out.println("clear()方法的异常: " + e);
        }
        try {
            c.add("X");
        } catch (Exception e) {
            System.out.println("add()方法的异常: " + e);
        }
        try {
            c.addAll(c2);
        } catch (Exception e) {
            System.out.println("addAll()方法的异常: " + e);
        }
        try {
            c.remove("C");
        } catch (Exception e) {
            System.out.println("remove()方法的异常: " + e);
        }
        // list.set() 方法修改值,但是没有改变数据结构的大小
        try {
            list.set(0, "X");
        } catch (Exception e) {
            System.out.println("list.set()方法的异常: " + e);
        }
    }
    public static void main(String[] args) {
        List<String> list = Arrays.asList("A B C D E F G H I J K L".split(" "));
        test("复制操作: ", new ArrayList<String>(list));
        System.out.println("**********一条华丽的分割线**********");
        test("Arrays.asList的操作: ", list);
        test("unmodifiableList()的操作: ", Collections.unmodifiableList(list));
    }
}

执行结果:

---- 复制操作: ----
**********一条华丽的分割线**********
---- Arrays.asList的操作: ----
retainAll()方法的异常: java.lang.UnsupportedOperationException
removeAll()方法的异常: java.lang.UnsupportedOperationException
clear()方法的异常: java.lang.UnsupportedOperationException
add()方法的异常: java.lang.UnsupportedOperationException
addAll()方法的异常: java.lang.UnsupportedOperationException
remove()方法的异常: java.lang.UnsupportedOperationException
---- unmodifiableList()的操作: ----
retainAll()方法的异常: java.lang.UnsupportedOperationException
removeAll()方法的异常: java.lang.UnsupportedOperationException
clear()方法的异常: java.lang.UnsupportedOperationException
add()方法的异常: java.lang.UnsupportedOperationException
addAll()方法的异常: java.lang.UnsupportedOperationException
remove()方法的异常: java.lang.UnsupportedOperationException
list.set()方法的异常: java.lang.UnsupportedOperationException

产生的原因

调用Arrays.asList()生产的List的add、remove方法时报异常,这是由Arrays.asList() 返回的是Arrays的内部类ArrayList, 而不是java.util.ArrayList。Arrays的内部类ArrayList和java.util.ArrayList都是继承AbstractList,remove、add等方法AbstractList中是默认throw UnsupportedOperationException而且不作任何操作。java.util.ArrayList重新了这些方法而Arrays的内部类ArrayList没有重新,所以会抛出异常。解决方法如下:

通过再新建一个ArrayList,让这些方法重新实现AbstractList的方法,如下图:

以下内容摘自Java编程思想(第四版):

因为Arrays.asList()会生成一个List,它基于一个固定大小的数组,而这个数组仅支持那些不会改变数组大小的操作。任何会引起对底层数据结构的尺寸进行修改的方法都会产生一个UnsupportedOperation Exception异常,以表示对未获支持操作的调用(一个编程错误)。

注意,应该把Arrays.asList()的结果作为构造器的参数传递给任何Collection(或者使用addAll()方法,或者 Collections.addAll()静态方法),这样可以生成允许使用所有的方法的普通容器----这在 main()方法中的第一个对test的调用中得到了展示,这样的调用会产生新的尺寸可调的底层数据结构。 Collections类中的“不可修改”的方法将容器包装到了一个代理中,只要你执行任何试图修改容器的操作,这个代理都会产生UnsupportedOperationException异常。使用这些方法的目标就是产生“常量”容器对象。“不可修改”的Collections方法的完整列表将在稍后介绍。

test方法中的最后一个try语句块将检查作为List的一部分的set()方法。这很有趣,因为你可以看到“未获支持的操作”这一技术的粒度来的是多么方便----所产生的“接口”可以在Arrays. asListCollections()返回的对象和Collections.unmodifiableList()返回的对象之间,在一个方法的粒度上产生变化。 Arrays.asList()返回固定尺寸的List,而 Collections. unmodifiableListO产生不可修改的列表。正如从输出中所看到的,修改 Arrays. asList()返回的List中的元素是可以的,因为这没有违反该List“尺寸固定”这一特性但是很明显,unmodifiableList()的结果在任何情况下都应该不是可修改的。如果使用的是接口,那么还需要两个附加的接口,一个具有可以工作的set()方法,另外一个没有,因为附加的接口对于 Collection的各种不可修改的子类型来说是必需的。

 

【参考资料】

1、Java编程思想(第四版)

 


目录
打赏
0
1
1
0
17
分享
相关文章
|
3月前
|
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
121 1
如何避免 Java 中的 TimeoutException 异常
在Java中,`TimeoutException`通常发生在执行操作超过预设时间时。要避免此异常,可以优化代码逻辑,减少不必要的等待;合理设置超时时间,确保其足够完成正常操作;使用异步处理或线程池管理任务,提高程序响应性。
212 13
|
3月前
|
在 Java 中,如何自定义`NumberFormatException`异常
在Java中,自定义`NumberFormatException`异常可以通过继承`IllegalArgumentException`类并重写其构造方法来实现。自定义异常类可以添加额外的错误信息或行为,以便更精确地处理特定的数字格式转换错误。
66 1
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
73 14
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
54 7
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
59 5
【Bug合集】——Java大小写引起传参失败,获取值为null的解决方案
类中成员变量命名问题引起传送json字符串,但是变量为null的情况做出解释,@Data注解(Spring自动生成的get和set方法)和@JsonProperty
【潜意识java】前后端跨域问题及解决方案
本文深入探讨了跨域问题及其解决方案。跨域是指浏览器出于安全考虑,限制从一个域加载的网页请求另一个域的资源。
87 0
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####
怎样避免 Java 中的 NoSuchFieldError 异常
在Java中避免NoSuchFieldError异常的关键在于确保类路径下没有不同版本的类文件冲突,避免反射时使用不存在的字段,以及确保所有依赖库版本兼容。编译和运行时使用的类版本应保持一致。
132 8

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等