调用Map#put()

时间:2015-12-19 11:27:57

标签: java generics compiler-warnings

我构建了一个接收通用对象的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);
    }
}

在这里你可以看到编译器抱怨的地方:

Code screenshot

3 个答案:

答案 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的引用应该参数化

这正是我写的。从他们出现的第一行开始阅读警告总是很好的建议。