使用Collections.unmodifiableMap()方法解析,实现返回不可修改的集合。

在实际项目开发中,有时候需要方法返回不可修改的集合或对象,比如:Map。

如以下例子:

/** 缓存的Map */
private static Map<String, String> cachedMap = new HashMap<>();

/** 刷新缓存 */
private static void reloadCache() {
    // ...
}

/** 获取缓存的Map */
public static Map<String, String> getCachedMap() {
    return cachedMap;
}

cachedMap作为私有对象,使得只有通过getCachedMap()方法获取缓存的Map。

但是由于返回的是引用,其它调用到的地方获取到返回的Map后还是可以对其进行修改,这不符合闭合原则。我们希望返回的是副本或通过某种办法让其不能修改。

在java.util包中的Collections类有个unmodifiableMap方法,可以简单的解决上述问题,查看其源码:

public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {
    return new UnmodifiableMap<>(m);
}

private static class UnmodifiableMap<K,V> implements Map<K,V>, Serializable {
    private static final long serialVersionUID = -1034234728574286014L;

    private final Map<? extends K, ? extends V> m;

    UnmodifiableMap(Map<? extends K, ? extends V> m) {
        if (m==null)
            throw new NullPointerException();
        this.m = m;
    }

    public int size()                        {return m.size();}
    public boolean isEmpty()                 {return m.isEmpty();}
    public boolean containsKey(Object key)   {return m.containsKey(key);}
    public boolean containsValue(Object val) {return m.containsValue(val);}
    public V get(Object key)                 {return m.get(key);}

    public V put(K key, V value) {
        throw new UnsupportedOperationException();
    }
    public V remove(Object key) {
        throw new UnsupportedOperationException();
    }
    public void putAll(Map<? extends K, ? extends V> m) {
        throw new UnsupportedOperationException();
    }
    public void clear() {
        throw new UnsupportedOperationException();
    }
    
    // ...
}

可以发现,unmodifiableMap方法返回的是一个UnmodifiableMap包装类。这个类里面保存了一个Map成员属性m。同时这个类也实现了Map接口,说明它具有Map的所有特性。

  • 当调用其读相关方法(size、isEmpty、get)时,间接调用的是成员属性m的对应方法。
  • 当调用其修改相关方法(put、remove、clear)时,直接抛出UnsupportedOperationException异常,不让修改。

所以,Collections.unmodifiableMap()方法通过返回一个UnmodifiableMap包装类实现返回的Map不可修改,其原理简单、调用方便。

但还需要注意的是:如果Map的value是对象类型的话,如:Map,虽然User本身引用不能修改,但是可以通过拿到User引用修改User内部数据。

同理:Collections除了unmodifiableMap,还有unmodifiableCollection、unmodifiableList、unmodifiableSet等方法,其原理是类似的:
使用Collections.unmodifiableMap()方法解析,实现返回不可修改的集合。_第1张图片

你可能感兴趣的:(Java开发)