小言_互联网的博客

Java的List之坑系列--Collections#unmodifiableList仍然可变

419人阅读  评论(0)

原文网址:Java的List之坑系列--Collections#unmodifiableList仍然可变_IT利刃出鞘的博客-CSDN博客

简介

说明

        本文介绍Collections#unmodifiableList的坑:本不可变的集合却被改变了。

        Collections#unmodifiableList是保护集合的,让集合不可变,本文介绍它被改变的情况。

Collections#unmodifiableList简介

        为了防止 List 集合被误操作,可用Collections#unmodifiableList生成一个不可变(immutable)集合,进行防御性编程。这个不可变集合只能被读取,不能做写操作,包括增加,删除,修改,从而保护不可变集合的安全。

        原理:返回的集合没有实现增删改的方法。

示例:


  
  1. package org.example.a;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.Collections;
  5. import java.util.List;
  6. public class Demo {
  7. public static void main (String[] args) {
  8. List<String> list = new ArrayList<>(Arrays.asList( "one", "two", "tree"));
  9. List<String> unmodifiableList = Collections.unmodifiableList(list);
  10. // 以下三行都会抛出UnsupportedOperationException 异常
  11. unmodifiableList.add( "four");
  12. unmodifiableList.remove( 1);
  13. unmodifiableList.set( 0, "test");
  14. }
  15. }

 结果


  
  1. Exception in thread "main" java.lang.UnsupportedOperationException
  2.     at java.util.Collections $UnmodifiableCollection. add(Collections. java: 1055)
  3.     at org.example.a.Demo. main(Demo. java: 12)

问题复现

如果使用不当,Collections#unmodifiableList操作后的List也是可能会被改变的。

代码


  
  1. package org.example.a;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.Collections;
  5. import java.util.List;
  6. public class Demo {
  7. public static void main (String[] args) {
  8. List<String> list = new ArrayList<>(Arrays.asList( "one", "two", "tree"));
  9. List<String> unmodifiableList = Collections.unmodifiableList(list);
  10. list.set( 0, "one_modified");
  11. System.out.println(unmodifiableList.get( 0));
  12. }
  13. }

执行结果

one_modified

 可见,被修改了!

原因分析

Collections#unmodifiableList


  
  1. public static <T> List<T> unmodifiableList (List<? extends T> list) {
  2. return (list instanceof RandomAccess ?
  3. new UnmodifiableRandomAccessList<>(list) :
  4. new UnmodifiableList<>(list));
  5. }

  
  1. static class UnmodifiableList<E> extends UnmodifiableCollection<E>
  2. implements List<E> {
  3. private static final long serialVersionUID = - 283967356065247728L;
  4. final List<? extends E> list;
  5. UnmodifiableList(List<? extends E> list) {
  6. super(list);
  7. this.list = list;
  8. }
  9. ...
  10. }

跟前边subList方法一样的情况:新集合底层实际使用(引用)了原始 List

解决方法

法1:JDK1.9的List#of 方法


  
  1. List<String> list = new ArrayList<>(Arrays.asList( "one", "two", "three"));
  2. List<String> unmodifiableList = List.of(list.toArray( new String[]{}));

法2:Guava包的ImmutableList


  
  1. List<String> list = new ArrayList<>(Arrays.asList( "one", "two", "three"));
  2. List<String> unmodifiableList = ImmutableList.copyOf(list);


转载:https://blog.csdn.net/feiying0canglang/article/details/127651732
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场