我正在寻找一种在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);
这是否存在或是否有解决方法?
编辑:我知道我可以通过铸造东西解决它,但我想知道是否有一种更优雅的方式,不需要我投射我所追溯的每一个价值。
答案 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
}
}
我承认,还有一项额外的工作,但是......