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

 


相关文章
|
4天前
|
Java
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
|
4天前
|
Java
在 Java 中,如何自定义`NumberFormatException`异常
在Java中,自定义`NumberFormatException`异常可以通过继承`IllegalArgumentException`类并重写其构造方法来实现。自定义异常类可以添加额外的错误信息或行为,以便更精确地处理特定的数字格式转换错误。
|
5天前
|
IDE 前端开发 Java
怎样避免 Java 中的 NoSuchFieldError 异常
在Java中避免NoSuchFieldError异常的关键在于确保类路径下没有不同版本的类文件冲突,避免反射时使用不存在的字段,以及确保所有依赖库版本兼容。编译和运行时使用的类版本应保持一致。
|
6天前
|
Java 编译器
如何避免在 Java 中出现 NoSuchElementException 异常
在Java中,`NoSuchElementException`通常发生在使用迭代器、枚举或流等遍历集合时,尝试访问不存在的元素。为了避免该异常,可以在访问前检查是否有下一个元素(如使用`hasNext()`方法),或者使用`Optional`类处理可能为空的情况。正确管理集合边界和条件判断是关键。
|
7天前
|
人工智能 监控 数据可视化
Java智慧工地信息管理平台源码 智慧工地信息化解决方案SaaS源码 支持二次开发
智慧工地系统是依托物联网、互联网、AI、可视化建立的大数据管理平台,是一种全新的管理模式,能够实现劳务管理、安全施工、绿色施工的智能化和互联网化。围绕施工现场管理的人、机、料、法、环五大维度,以及施工过程管理的进度、质量、安全三大体系为基础应用,实现全面高效的工程管理需求,满足工地多角色、多视角的有效监管,实现工程建设管理的降本增效,为监管平台提供数据支撑。
24 3
|
9天前
|
Java
Java异常捕捉处理和错误处理
Java异常捕捉处理和错误处理
11 1
|
11天前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
26 2
|
13天前
|
Java API Apache
|
18天前
|
Java
如何在 Java 中处理“Broken Pipe”异常
在Java中处理“Broken Pipe”异常,通常发生在网络通信中,如Socket编程时。该异常表示写入操作的另一端已关闭连接。解决方法包括:检查网络连接、设置超时、使用try-catch捕获异常并进行重试或关闭资源。
|
20天前
|
存储 安全 Java
如何避免 Java 中的“ArrayStoreException”异常
在Java中,ArrayStoreException异常通常发生在尝试将不兼容的对象存储到泛型数组中时。为了避免这种异常,确保在操作数组时遵循以下几点:1. 使用泛型确保类型安全;2. 避免生类型(raw types)的使用;3. 在添加元素前进行类型检查。通过这些方法,可以有效防止 ArrayStoreException 的发生。