2013-08-27 50 views
0

我想实现Map接口,但将K和V绑定到接口)。但是,考虑到Java集合API,特别是MAP接口至少会限制方法参数,请使用Object而不是通用类型K和V.例如,接口指定:public boolean containsValue(Object value)而不是public boolean containsValue(V value)。在这种场合我不能依靠编译器类型的安全性。为Map实现强制类型参数的属性(如接口中)

需要明确的是,我要实现类似如下:

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

你的第二个陈述是什么意思? –

+0

这个问题有一些有趣的答案,为什么'Map'接口不使用通用类型的某些方法参数:http://stackoverflow.com/questions/857420/what-are-the-reasons-why-map-getobject关键不是完全通用的 – andersschuller

+0

@RohitJain我编辑了这个问题。希望它更好地知道。但是代码举例说明,由于接口契约,我必须处理一个对象,但我希望V确信我有可能依赖于ValueInterface属性。 – fabiim

回答

1

这是Map的接口合同 - 因此您必须按照原样执行合同。

不过,我认为有两个原因,为什么Map这部分的设计是一件好事:

i)本Mapcontract是,你可以在下列情况下得到的映射值:

如果此映射包含从密钥k到值v的映射,使得 (key == null?k == null:key.equals(k)),则此方法返回v; 否则返回null。如果此映射包含指定键的映射关系

返回true:(可以有至多一个这样的映射。)

或等价,而具体到你的问题有关containsKey(Object key)。更正式地说,当且仅当此映射包含关键字k的映射(key == null?k == null:key.equals(k))时才返回true。 (可以有至多一个这样的映射。)

这样,你不关心打字,而是平等

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键(你会得到一个运行时异常...)。你决定如何实现它取决于你的设计。让我们设想一下,你在保存类型列表中的键和值...然后你会被告知铸造前检查instanceofObject键:

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?” ......

+0

我有这样的感觉,因为基于平等的实现契约是这样的。这对我来说听起来很糟糕,因为它看起来像让实现细节逃到了界面的设计中。但是,在这个问题的具体背景下,我真的不关心这个决定背后的原因。我只想知道我是否应该:避免实现Map或者通过cast来解决这个问题(小心使用instanceof off course)或者其他一些我不知道的通用魔法。 – fabiim

+1

@fabiim - Map接口中的这​​种设计是一件好事(你应该关心它,因为理解它为什么是好东西会更好地使你能够在Java中使用泛型)。 Java泛型没有任何魔力 - 它们是该语言中非常有用的一部分,尽管这需要一些时间和精力来学习/理解。至于你的特定用法,这一切都取决于你想要达到的目标......目前你的原始问题是“我想实现Map接口...”,对此(不出意外)你需要实现地图界面。 – amaidment

0

如果你想要实现Map<K,V>你将被要求实现接口中的所有方法。

你可以扩展AbstractMap<K,V>并覆盖抽象方法,再加上您要自定义行为的任​​何非抽象方法(只要你不违反合同Map)。

+0

因此,本质上,你的答案是:那么,除了投射外,你什么都不能做并希望更好(如果你想实施地图):) – fabiim

+0

不幸的是,是的。 'Map'接口最初是在泛型之前设计的,我想更改签名会破坏现有的代码。 –

相关问题