在HashMap中使用嵌套泛型类型

时间:2018-06-09 14:04:18

标签: java dictionary generics hashmap

我正在寻找一种在Map类型中使用泛型类型Map的方法,然后使用键和正确的类型来检索那些类型。例如:

private final <T> Map<A<T>,B<T>> map = new HashMap<>();

public <T> B<T> getB(final A<T> a) {
  return map.get(a);
}

使用它的一个例子是:

final A<String> a = ...;
final B<String> b = getB(a);

这是否存在或是否有解决方法?

编辑:我知道我可以通过铸造东西解决它,但我想知道是否有一种更优雅的方式,不需要我投射我所追溯的每一个价值。

2 个答案:

答案 0 :(得分:6)

您无法以这种方式声明地图。基本上,Java没有足够表达的类型系统。

但幸运的是,该语言以强制转换的形式提供了使用类型系统的逃避方法。基本上,强制转换是一种提供编译器没有的类型信息的方法;然而,你有责任确保它实际 类型安全。

首先,使用通配符类型声明地图:

private final Map<A<?>,B<?>> map;

然后,只将键/值对放入符合约束的地图中:

<T> void put (A<T> key, B<T> value) {
  map.put(key, value);
}

当你再次获得元素时再进行投射:

@SuppressWarnings("unchecked") // Safe
<T> B<T> get(A<T> key) {
  return (B<T>) map.get(key);
}

关键是你可以比编译器更多地了解类型。如果您只注意安装可安全浇注的对,则可以安全地进行铸造。 (您还需要确保equals方法考虑到类型,因此A<T>等于A<S>,除非S == T)。

这基本上是一个“类型安全的异构容器”,如 Effective Java (第3版第33项)中所述。

  

我想知道是否有一种更优雅的方式,不需要我投射我所追溯的每一个价值。

首先,你实际上并没有在运行时使用get方法进行强制转换:这就是未经检查的强制转换的含义。

另一方面,泛型引入了强制转换的加载 - 基本上泛型只是一种避免手动插入强制转换的方法。因此,如果演员表存在问题(例如表演),你已经在很多地方都观察到了这一点。

用Kubrick的话来解释:不要担心,并且喜欢演员。

答案 1 :(得分:-4)

好吧,我被挑衅发布这个答案作为一种OOP原则的观点。

在问题Map<A<T>,B<T>>中,所以我的方法是做这样的事情:

class A<T> {}
class B<T> {}

public class Answer {

    public static void main(String[] args) {

        Map<A, B> map = new HashMap<>();
        A<Integer> a = new A<>(); //very safe
        B<String> b = new B<>(); //very safe

        map.put(a, b); //very safe

    }

}

我承认,还有一项额外的工作,但是......