Collections踩坑UnsupportedOperationException

Collections是什么?

Collections是Java.util包下提供的一个工具类,相信大家不陌生,在我们的代码中也不乏其身影。因为其提供的静态API十分便捷地帮助我们完成对集合的相关操作,也让我们的代码也变得更加优雅。

Collections常用的API

在这里插入图片描述

一般情况下,我们在业务代码的编写中,使用频率最高的,就是借助Collections来创建集合了。这里我将其划分成为两部分:同步集合不可修改集合。同步集合不用我多说了,就是将传入的集合进行包装,所有的方法都加上synchronized关键字,确保方法同步来保证线程安全。而不可修改集合的意思,就是该类集合不允许修改,只允许读。

Collections为我们提供方便的同时,我们要需要注意使用恰当,否则一不留神就会抛出UnsupportedOperationException。下面我就已list为例,来聊聊使用Collections来创建集合需要注意的地方。

Collections.emptyList()

业务场景:后台返回一个空列表到前端。(注意:空列表不能传null,否则前端解析会出差错,坑点!!!)

我们很自然会使用new ArrayList()Collections.emptyList()来创建空集合,返回给前端。这时强烈建议把Collections.emptyList()代码放在cotroller层使用,不要放在service层。否则别人调用service层方法时,不了解情况就会引发灾难。

public class ControllerTest {
    /**
     * 模拟controller中的方法
     * @return
     */
    public List<String> doController() {
        Service service = new Service();
        List<String> list = service.doService();
        list.add("我要添加一个元素"); // 此处抛出UnsupportedOperationException
        return list;
    }
}

class Service {
    /**
     * 模拟service方法, 返回空集合
     * @return
     */
    public List<String> doService() {
        return Collections.emptyList();
    }
}

查看源码可以看到EmptyList是继承AbstractList,而AbstractList的add()是没有实现的,调用add()会直接抛出UnsupportedOperationException

private static class EmptyList<E> extends AbstractList<E> {}
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
    public boolean add(E e) {
        add(size(), e);
        return true;
    }
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
}

Collections.SingletonList()

业务场景:创建一个集合,往里面添加一个元素。

这时一般情况下,会选择这两种创建方式new ArrayList().add(Object obj)Arrays.asList(Object obj)。有时我们为了让我们的代码看起来更优(bi)雅(ge),会选择使用Collections.SingletonList(Object obj),在不经意之间引发了一场灾难,可谓欢声笑语中打出了GG。

同样查看源码得知,SingletonList也是继承AbstractListAbstractList中无论是add()和remove()方法都没有实现的,调用会直接抛出UnsupportedOperationException。同时强烈建议将Collections.SingletonList(Object obj)放在cotroller层使用,不要放在service层。

值得注意是:Arrays.asList(Object obj)返回的也是AbstractList,同样会面临上述问题。

private static class SingletonList<E> extends AbstractList<E> implements RandomAccess, Serializable {}

Collections.UnmodifiableList()

Collections.UnmodifiableList()见名知义,返回一个不可不修改的集合。其add()和remove()方法都会抛出UnsupportedOperationException

static class UnmodifiableList<E> extends UnmodifiableCollection<E> implements List<E> {
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
    public E remove(int index) {
        throw new UnsupportedOperationException();
    }
}

小总结

Collections给我带来便利的同时,我们要也注意其使用场景,否则就会给我们带来闹心的bug。我们使用Collections创建的集合时,注意这些集合是不可修改的,就要留意使用过程中有没有可能被修改,否则我们还是老老实实的使用new ArrayList吧。同样我们还需要注意别人有没有可能调用我们的方法,进而修改我们的集合。除非我们有强烈的目的来防止别人修改,否则还是将这些方法放到Cotroller层使用,更为保妥一点。


版权声明:本文为kaoya156原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。