Java - 扩展 HashMap - 对象与泛型行为

标签 java generics inheritance casting

我正在编写一个简单的基于 HashMap 的缓存,其工作方式如下:

  1. 如果请求的缓存中,返回它的
  2. 如果请求的key,运行一个方法根据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);
}

它非常简单并且运行良好。但是,我讨厌 Sun 决定get()Object 作为参数而不是K。我已经阅读了足够多的内容,知道它背后有一些基本原理(我不同意,但那是另一个故事)。

我的问题出在注释行中,因为看起来 Actor 必须 未选中。由于类型删除,我无法检查 key 是否属于 K 类型(这是正确的 put() 功能所必需的)和因此,该方法很容易出错。

一个解决方案是从“是一个”切换到“有一个”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);
}

任何人都可以想出任何其他(甚至是 hackish)解决方案,以便我可以将 Cache 维护为 Map 并且仍然是类型安全的 get(Object key)put(K key, V val)?

我唯一能想到的是创建另一个名为 getValue(Key k) 的方法,它将委托(delegate)给 get(Object key),但我可以'强制任何人使用新方法而不是通常的方法。

最佳答案

没有。您已经找到了切换到“拥有”关系的正确解决方案。 (坦率地说,让 get 方法计算一个新值(如果一个值尚不存在)是令人惊讶的,这违反了 Map 契约,并且可能导致许多其他方法出现极其奇怪的行为。这是为什么 Guava 离开了 MapMaker ,它提供了几乎完全相同的行为——因为它是如此 riddled 有问题。)

就是说,例如 Guava 的Cache是它暴露了一个 Map<K, V> asMap() 查看,这是您可以做的事情。这为您提供了 Map 的大部分优势不影响类型安全。

关于Java - 扩展 HashMap - 对象与泛型行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10354103/

相关文章:

java - ExceptionMapper的执行顺序

java - 如果我实现 List 并在接受 List< 的方法中调用 add 会怎样?扩展父类(super class)型>

java - Kotlin 与 Java 嵌套泛型

c# - 看到 "cannot convert expression to type while using a generic method"时我做错了什么?

c# - 我们应该密封单例吗?我们应该首先尝试继承单例吗?

java - 安卓Java : Choose dynamically a subtype class

java - 循环遍历 Java 数组并追加 () 到 TextArea

java - Play Framework 2.2 如何设置响应覆盖调用操作中的状态代码

java - NullPointerException 将子字符串从字符串添加到数组列表

c# - 多态/覆盖