Pet*_*ček 15 java generics inheritance casting
我正在编写一个HashMap基于简单的Cache,其工作方式如下:
key 是在缓存中,返回它value.key 不存在,则运行value基于生成的方法key,存储两者,返回value.代码:
import java.util.HashMap;
abstract class Cache<K, V> extends HashMap<K, V> {
@Override
public V get(Object key) {
if (containsKey(key)) {
return super.get(key);
} else {
V val = getData(key);
put((K)key, val); // this is the line I'm discussing below
return val;
}
}
public abstract V getData(Object key);
}
Run Code Online (Sandbox Code Playgroud)
这很简单,效果很好.但是,我讨厌太阳的决策get()采取的Object作为它的参数,而不是K.我已经阅读了足够的知识,知道它背后有一些理由(我不同意,但这是另一个故事).
我的问题是在注释行,因为它似乎投有被选中.由于类型擦除,我无法检查是否key为类型K(正确put()功能所需),因此该方法容易出错.
一种解决方案是从"is a"切换到"has a" HashMap关系,这种关系更加美观和干净,但是由于几个原因Cache无法实现Map哪种方式会很好.代码:
import java.util.HashMap;
import java.util.Map;
abstract class Cache<K, V> {
private final Map<K, V> map = new HashMap<K, V>();
public V get(K key) {
if (map.containsKey(key)) {
return map.get(key);
} else {
V val = getData(key);
map.put(key, val);
return val;
}
}
public abstract V getData(K key);
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以提出任何其他(甚至是hackish)解决方案,以便我可以保持Cache成为一个Map并且仍然是类型安全的get(Object key)和put(K key, V val)?
我能想到的唯一的事情就是让命名即另一种方法getValue(Key k),将委托给get(Object key),但我不能强迫任何人使用新的方法,而不是往常的.
Lou*_*man 15
不.您已经找到了切换到"has-a"关系的正确解决方案.(坦率地说,get如果一个尚未存在的方法计算一个新值是令人惊讶的,违反了Map合同,并且可能导致许多其他方法的极其奇怪的行为.这是Guava离开的原因的一个重要部分MapMaker,它几乎提供了这种确切的行为 - 因为它只是如此充满了问题.)
也就是说,例如Guava Cache所做的是它暴露了一个Map<K, V> asMap() 视图,这是你可以做的事情.这样可以在Map不影响类型安全的情况下为您提供大部分优势.
| 归档时间: |
|
| 查看次数: |
22326 次 |
| 最近记录: |