【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编程思想(第四版)

 


相关文章
|
22天前
|
Java 开发者 UED
【实战宝典】Java异常处理大师级教程:throws关键字,让异常声明成为你的专属标签!
【实战宝典】Java异常处理大师级教程:throws关键字,让异常声明成为你的专属标签!
35 3
|
2天前
|
Java 编译器 数据库连接
Java——异常
在 Java 中,程序执行过程中的不正常行为被称为异常。异常分为 Error 和 Exception。Error 表示系统级错误,而 Exception 则封装程序可能出现的问题。异常包括编译时异常和运行时异常(如数组越界)。异常可用于查找 bug 信息和作为方法内部的特殊返回值。处理异常的方式有默认处理和捕获异常,后者通过 try-catch 结构实现。此外,还可以自定义异常类来更灵活地处理特定情况。
18 9
Java——异常
|
5天前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
23天前
|
人工智能 小程序 Java
【Java】throw异常后代码还执行吗?80%小伙伴竟然不知道
本文通过具体的Java代码示例,探讨了Java异常处理机制下的程序流程变化,包括未使用try-catch时异常导致流程中断、使用try-catch捕获异常后的不同执行路径、循环中的异常处理以及throw抛出异常后的代码执行情况。总结了异常处理的关键点,强调了finally块的重要性。
42 4
【Java】throw异常后代码还执行吗?80%小伙伴竟然不知道
|
22天前
|
Java 数据库连接 程序员
Java 认识异常
Java 认识异常
11 1
|
22天前
|
搜索推荐 Java 开发者
Java异常处理新高度:自定义异常,打造个性化的错误管理体系!
Java异常处理新高度:自定义异常,打造个性化的错误管理体系!
30 1
|
22天前
|
前端开发 Java
Java高手都在用的秘籍:自定义异常,让错误信息说话!
Java高手都在用的秘籍:自定义异常,让错误信息说话!
34 1
|
22天前
|
Java 程序员 开发者
我们踩过的Java坑:自定义异常,让你的代码不再“捉急”!
我们踩过的Java坑:自定义异常,让你的代码不再“捉急”!
31 1
|
24天前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
|
16天前
|
Java C++
Java内存区域于内存溢出异常
这篇文章详细解释了Java虚拟机的内存区域划分、各区域的作用以及可能遇到的内存溢出异常情况。
29 0