对Map实现的类型参数强制属性(如在接口中)

时间:2013-08-27 21:25:51

标签: java generics collections override type-erasure

我想实现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... 
}

在这种情况下,我有哪些选项和/或最佳做法?

2 个答案:

答案 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}合同)。