我构建了一个接收通用对象的Java类;
仅限课程字段设置为:
private Map map = new HashMap<T,Integer>();
我的问题是,在我编写的某些方法中,当我为HashMap对象调用put
方法并且编译器警告我和diaplay后面的消息:
类型安全:方法
put(Object, Object)
属于原始类型HashMap。对泛型类型Map<K,V>
的引用应该参数化
我更喜欢避免编译器警告,因为它可能以运行时错误结束。
如果你能解释我的信息以及我需要做些什么来消除它,我将很高兴。
我写的方法是:
public void addItem(T item) {
if (this.map.containsKey(item)) {
this.map.put(item, (int)this.map.get(item) + 1);
}
else {
this.map.put(item, 1);
}
}
在这里你可以看到编译器抱怨的地方:
答案 0 :(得分:2)
更改
private Map map = new HashMap();
到
private Map<Type1, Type2> map = new HashMap<>();
Type1
&amp; Type2
是地图key
&amp;的地名。 value
(分别)
例如,要声明由String
索引的Integer
值的地图:
(请注意,您不能使用原始类型)
private Map<Integer, String> map = new HashMap<>();
您的方法的缺点可以在您的方法的第3行看到,其中需要向下投射。显然,如果键值对已被不同的值类型替换,这可能会导致 ClassCastException 。 (在这种情况下,您正在向下转换为int
,这是无效的)
通过参数化地图,您强制要包含的对象类型(或要使用的键的类型)
答案 1 :(得分:0)
声明的map类型是unparametrized接口,编译器检查声明的类型,而不是实际的类型。
答案 2 :(得分:0)
如果要正确使用泛型,仅在实例化中使用它们是不够的(=通过调用new
运算符创建一个新对象)new HashMap<T,Integer>()
,但是你还应该< em>使用泛型声明你的变量:
private Map<T,Integer> map = new HashMap<T,Integer>();
从Java 7开始,您不必在实例化中重复类型,因为编译器足够聪明,可以从声明中推断(=推断)正确的类型。这意味着你可以只写
private Map<T,Integer> map = new HashMap<>();
构造<>
根据其形状称为菱形算子。
您的编译器抱怨使用没有泛型的Map
,这称为原始类型。
我相信你没有正确复制警告信息。我的编译器说
类型安全:方法put(Object,Object)属于原始类型 Map 。
注意地图,而不是HashMap。因为编译器不能(通常)知道您为map
变量分配了哪个实际实例。因此,编译器抱怨变量 map
的原始类型,而不是其实际的内容。
编译器应该已经在声明
中抱怨(除非你以某种方式压制它)private Map map = new HashMap<T,Integer>();
地图是原始类型。对泛型类型Map的引用应该参数化
这正是我写的。从他们出现的第一行开始阅读警告总是很好的建议。