我认为有一种方法可以有效(如果有的话)这样做,但我想我会问,以防其他人知道其他情况。我正在寻找创建自己的缓存/查找表。为了使它尽可能有用,我希望它能够存储通用对象。这种方法的问题在于,即使您可以创建Collections.unmodifiableMap, immutableMap, etc
,这些实现也只会阻止您更改Map本身。它们不会阻止您从地图中获取值并修改其基础值。基本上我需要的是HashMap<K, ? extends Immutable>
的效果,但据我所知,这样的事情就不存在了。
我原本以为我可以在get方法中返回缓存中值的副本,但是由于Java的Cloneable
接口被抬起,你不能简单地调用
public V getItem(K key){
return (V) map.get(k).clone();
}
答案 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)
语言中没有“可变性”或“不变性”的正式概念。编译器无法判断类型是“可变”还是“不可变”。为了确定某些东西是不可变的,我们人类必须检查类的每个字段和方法,并通过方法的行为来推断它们都不会改变对象的状态,然后我们称之为“不可变”。但是从语言的角度来看没有区别。