当前位置:首页 » 《随便一记》 » 正文

java.lang.UnsupportedOperationException分析及解决

14 人参与  2024年03月06日 08:26  分类 : 《随便一记》  评论

点击全文阅读


        今天在写业务的时候,需要对从数据库返回的List集合根据对象属性进行排序,那么常规的做法就是使用Collections的sort方法,实现Compartor接口重写compare方法,或者直接使用该list的sort方法,但是无论使用那种方法都遇到了这样的报错原因: 

java.lang.UnsupportedOperationException: nullat java.util.Collections$UnmodifiableList.sort(Collections.java:1333) ~[na:1.8.0_331]at java.util.Collections.sort(Collections.java:177) ~[na:1.8.0_331]

         无法支持的操作,再看报错第二行UnmodifiableList,这是一个不可变的集合,它继承 UnmodifiableCollection类,UnmodifiableCollection 中涉及到元素改动(新增、删除、清空…)的方法都直接抛出 UnsupportedOperationException 异常,并不改动元素;Iterator 中涉及到元素修改的方法也一样不进行元素的改动。

        那么是不是把这个集合变成可变的集合问题是不就解决了呢?

list = new ArrayList<>(list);

         在排序前给这个list再次封装,问题得以解决。

static class UnmodifiableList<E> extends UnmodifiableCollection<E>                                  implements List<E> {        private static final long serialVersionUID = -283967356065247728L;        final List<? extends E> list;        UnmodifiableList(List<? extends E> list) {            super(list);            this.list = list;        }        public boolean equals(Object o) {return o == this || list.equals(o);}        public int hashCode()           {return list.hashCode();}        public E get(int index) {return list.get(index);}        public E set(int index, E element) {            throw new UnsupportedOperationException();        }        public void add(int index, E element) {            throw new UnsupportedOperationException();        }        public E remove(int index) {            throw new UnsupportedOperationException();        }        public int indexOf(Object o)            {return list.indexOf(o);}        public int lastIndexOf(Object o)        {return list.lastIndexOf(o);}        public boolean addAll(int index, Collection<? extends E> c) {            throw new UnsupportedOperationException();        }        @Override        public void replaceAll(UnaryOperator<E> operator) {            throw new UnsupportedOperationException();        }        @Override        public void sort(Comparator<? super E> c) {            throw new UnsupportedOperationException();        }        public ListIterator<E> listIterator()   {return listIterator(0);}        public ListIterator<E> listIterator(final int index) {            return new ListIterator<E>() {                private final ListIterator<? extends E> i                    = list.listIterator(index);                public boolean hasNext()     {return i.hasNext();}                public E next()              {return i.next();}                public boolean hasPrevious() {return i.hasPrevious();}                public E previous()          {return i.previous();}                public int nextIndex()       {return i.nextIndex();}                public int previousIndex()   {return i.previousIndex();}                public void remove() {                    throw new UnsupportedOperationException();                }                public void set(E e) {                    throw new UnsupportedOperationException();                }                public void add(E e) {                    throw new UnsupportedOperationException();                }                @Override                public void forEachRemaining(Consumer<? super E> action) {                    i.forEachRemaining(action);                }            };        }        public List<E> subList(int fromIndex, int toIndex) {            return new UnmodifiableList<>(list.subList(fromIndex, toIndex));        }        /**         * UnmodifiableRandomAccessList instances are serialized as         * UnmodifiableList instances to allow them to be deserialized         * in pre-1.4 JREs (which do not have UnmodifiableRandomAccessList).         * This method inverts the transformation.  As a beneficial         * side-effect, it also grafts the RandomAccess marker onto         * UnmodifiableList instances that were serialized in pre-1.4 JREs.         *         * Note: Unfortunately, UnmodifiableRandomAccessList instances         * serialized in 1.4.1 and deserialized in 1.4 will become         * UnmodifiableList instances, as this method was missing in 1.4.         */        private Object readResolve() {            return (list instanceof RandomAccess                    ? new UnmodifiableRandomAccessList<>(list)                    : this);        }    }

        这里从UnmodifiableList的源码来分析:除了equals、hashCode、get、indexOf、lastIndexOf等方法外,其他方法都会抛出UnsupportedOperationException()异常,而这些方法的共同点都是返回该list的属性,说明UnmodifiableList是一个只读的集合,因此对这个List不能进行添加或删除元素等操作。

        如果需要将list转化为不可变的集合,Collections也提供了这样的方法,最终转化为UnmodifiableList。

  public static <T> List<T> unmodifiableList(List<? extends T> list) {        return (list instanceof RandomAccess ?                new UnmodifiableRandomAccessList<>(list) :                new UnmodifiableList<>(list));    }

        同样的 Collections 集合类中的 unmodifiableMap、unmodifiableSet也是只读内部类。它们可以在多线程环境下使用,或者在需要保护列表免受修改的场景下使用。


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/74430.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1