我已经这样实例化了HashMap:
Map<String, Integer> myHashMap = new HashMap<String, Integer>();
Key
的数据类型为String,因此当我尝试在地图中插入一个新的键值对时,将Key
保留为Integer,则会引发错误。
myHashMap.put(1L, "value");
这意味着在put方法中,他们限制了Key
的数据类型。但是,在使用get
方法从映射中获取值时,它并没有检查Key
的数据类型。因此,如果我写这样的东西,它不会给出编译错误。
myHashMap.get(1L);
我在Java Map界面中检查了get
方法,其参数类型为Object
,因此这就是为什么它允许将任何Object用作put方法参数的原因。
V get(Object key)
有没有办法限制在get
方法中作为参数传递的数据类型?
我传递的参数应该与实例化哈希映射时使用的Key
的数据类型相同。
答案 0 :(得分:17)
以这种方式设计,因为在获取操作期间,仅使用equals
和hashCode
来确定要返回的对象。 get
方法的实现不检查用作键的对象的类型。
在您的示例中,您尝试通过传递类似myHashMap.get(1L);
的长整数来获取值,首先,对象Long
的哈希码具有值1L
将用于确定从中寻找水桶。接下来,使用 key 的equals
方法来查找要从中返回值的映射的确切条目。并且在定义明确的equals
方法中,始终会检查类型:
public boolean equals(Object obj) {
if (obj instanceof Long) { //here type is checked
return value == ((Long)obj).longValue();
}
return false;
}
因此,如果类型不相等,则equals
方法将返回false
,因此get
也将返回null
。
在某些情况下,例如使用List
作为键时,可能会发生这样的情况:您使用诸如ArrayList
的实例在地图上放置了一个项目,但可以成功地使用检索相同的值LinkedList
的实例。由于两者都实现了List
接口。
Map<List<String>, String> myHashMap = new HashMap<>();
List<String> arrayList = new ArrayList<>();
List<String> linkedList = new LinkedList<>();
myHashMap.put(arrayList, "foo");
System.out.println(myHashMap.get(linkedList));
以上代码将在控制台foo
中输出。
尽管实现方式不同,但是如果您检查equals
的{{1}}方法,则仅检查类型是否为ArrayList
:
List
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof List)) { //checking type of super interface
return false;
}
...
}
也是如此。
答案 1 :(得分:4)
我认为,如果在我们控制HashMap中的类型的项目中非常重要,我们可以扩展HashMap并强制使用此类而不是像下面的代码那样使用HashMap。
我们具有所有HashMap功能,我们应该只使用getValue方法而不是get方法。
import java.util.HashMap;
public class MyHashMap<K,V> extends HashMap<K,V> {
public V getValue(K key) {
return super.get(key);
}
}
测试类:
public class Test {
public static void main(String[] args) {
MyHashMap<String,Integer> map = new MyHashMap();
}
}