我想实现Map接口,但是将K和V绑定到接口)。但是,鉴于Java集合API,特别是MAP接口至少限制了方法参数,使用Object而不是泛型类型K和V.举例说明接口指定:public boolean containsValue(Object value)
而不是public boolean containsValue(V value)
。在这种情况下我不能依赖编译器类型安全。
要明确,我想实现以下内容:
class MyMap< K , V extends ValueInterface> implements Map<K,V>
但是,我需要实现以下方法:
@Override
public boolean containsValue(Object value) {
// What to do here?
ValueInterface v = (ValueInterface ) v;
v.getWhatIWant().andDoThing();
// Follow on...
}
在这种情况下,我有哪些选项和/或最佳做法?
答案 0 :(得分:1)
这是Map
的接口合约 - 因此您必须按原样执行合约。
但是,让我提出两个原因,为什么设计这部分Map
是件好事:
i)Map
contract是您可以在以下情况下从地图获取值:
如果此映射包含从键k到值v的映射,则为p (key == null?k == null:key.equals(k)),则此方法返回v; 否则返回null。 (最多可以有一个这样的映射。)
或同等地,并且特定于您关于containsKey(Object key)
的问题:
如果此映射包含指定键的映射,则返回true。更正式地,当且仅当此映射包含键k的映射时才返回true(key == null?k == null:key.equals(k))。 (最多可以有一个这样的映射。)
因此,您不关心输入,而是关注平等。
ii)这真的是同一点,但请考虑以下几点:
Map<String, Integer> map = new HashMap<>();
String key = "A Key";
Integer value = 1;
map.put(key, value);
Object objectKey = key; // this is the same key object, but it is typed as Object
map.containsKey(objectKey); // what would you want/expect this to return?
map.get(objectKey); // ...or this?
因此,关于Map
的实现,我不建议只是转换Object
密钥(您将获得运行时异常......)。您决定如何实施它将取决于您的设计。让我们假设您将键和值存储在类型列表中......然后建议您在投射前检查instanceof
Object
键:
public boolean containsKey(Object key) {
if (key instanceof K) {
// do your thing...
} else {
return false;
}
}
请注意instanceof
检查基础对象的类型,而不是其声明的类型,因此:
String key = "A Key";
Object objectKey = key;
boolean isString = (objectKey instanceof String); // is true
真的,我建议不要问如何强制违反Map
合同的内容,而是要问问题"why is the contract that way?&#34; ...
答案 1 :(得分:0)
如果您想实施 Map<K,V>
,您将需要在界面中实现所有方法。
您可以扩展 AbstractMap<K,V>
并覆盖抽象方法,以及您想要自定义行为的任何非抽象方法(只要您不违反{{1}合同)。