创建不可变通用对象的哈希映射

时间:2013-12-24 21:46:16

标签: java generics caching

我认为有一种方法可以有效(如果有的话)这样做,但我想我会问,以防其他人知道其他情况。我正在寻找创建自己的缓存/查找表。为了使它尽可能有用,我希望它能够存储通用对象。这种方法的问题在于,即使您可以创建Collections.unmodifiableMap, immutableMap, etc,这些实现也只会阻止您更改Map本身。它们不会阻止您从地图中获取值并修改其基础值。基本上我需要的是HashMap<K, ? extends Immutable>的效果,但据我所知,这样的事情就不存在了。

我原本以为我可以在get方法中返回缓存中值的副本,但是由于Java的Cloneable接口被抬起,你不能简单地调用

public V getItem(K key){
    return (V) map.get(k).clone();
}

4 个答案:

答案 0 :(得分:5)

你的想法很好,而你没有内置的处理不变性的方法。

但是,你可以试试这个:

interface Copyable<T> {
    T getCopy();
}

然后覆盖get()方法以返回副本而不是值本身;

class CopyMap<K, V extends Copyable<V>> extends HashMap<K, V> {
    @Override
    public V get(Object key) {
        return super.get(key).getCopy();
    }
}

然后由实现来返回自身的副本,而不是this(除非类本身是不可变的)。虽然你不能在代码中强制执行,但你有权公开羞辱那些不符合的程序员。

答案 1 :(得分:2)

  

我正在寻找创建自己的缓存/查找表。

为什么不使用Guava的cache

  

这种方法的问题在于即使你可以制作一个   Collections.unmodifiableMap,immutableMap等,这些实现   只能阻止您更改Map本身。他们不会阻止你   从地图中获取值并修改其底层   值。

这不是任何集合可以为您强制执行的。您需要使类自己不可变。 是一种使用Reflection的hacky方法(它也可以用来使类可变!),但实际上,你应该避免这种情况,只需创建不可变的类。

答案 2 :(得分:1)

Java中还有其他对象克隆选项:Making a copy of an object Dynamically?

请注意,深度克隆任何对象可能都很危险。存储在此映射中的对象必须彼此隔离,以确保在返回单个条目时不会复制整个对象图。

答案 3 :(得分:1)

语言中没有“可变性”或“不变性”的正式概念。编译器无法判断类型是“可变”还是“不可变”。为了确定某些东西是不可变的,我们人类必须检查类的每个字段和方法,并通过方法的行为来推断它们都不会改变对象的状态,然后我们称之为“不可变”。但是从语言的角度来看没有区别。