如何解决这个Java类型的安全警告?

2022-09-04 20:01:13
Map session = ActionContext.getContext().getSession();
session.put("user", user);

此代码生成一个警告:类型安全:方法 put(Object, Object) 属于原始类型 Map。对泛型类型 Map<K,V> 的引用应参数化

Map<String, Serializable> session = (Map<String, Serializable>)ActionContext.getContext().getSession();
session.put("user", user);

此代码生成一条警告:键入安全:未选中从 Map 到 Map 的强制转换<字符串、可序列化>

getSession方法属于Struts2,所以我不能修改它。我想避免使用@SuppressWarnings,因为其他警告可能很有用。

我想世界上所有的Struts2用户都面临着同样的问题......有没有一个优雅的解决方案?


答案 1

我不认为有任何其他方法,但@SuppressWarnings(“未检查”)。我相信你可以把它放在有问题的线的上方,它只会抑制这条线。

编辑:你也可以做,但我不确定你有多愿意这样做;您将无法以这种方式将任何内容放入映射中(因为编译器无法检查您要放置的内容的类型),只能从中读取。Map<?, ?> session = ActionContext.getContext().getSession();


答案 2

处理这个问题的最安全,最有效的方法可能是:

Map<?, ?> session = ActionContext.getContext().getSession();

,然后键入从会话映射中检索到的对象的强制转换。

@SuppressWarnings方法实际上将导致编译的代码是相同的。但是,类型强制转换将是隐式的;也就是说,通过查看源代码并不容易发现。并且@SuppressWarnings注释可以(假设地)抑制表示真实错误的同一代码块中的其他一些警告;即,将导致一个隐藏的类型转换等在运行时失败。

其他更昂贵的替代方案包括:

  • 逐个条目从 复制到新实例,分别将键和值强制转换为 和,或者Map<?, ?>Map<String, Serializable>StringSerializable

  • 一个类似于以下内容的泛型方法,可以安全地执行类型转换。


@SuppressWarnings("unchecked")
public <K,V> Map<K,V> castMap(Map<?, ?> map, Class<K> kClass, Class<V> vClass) {
    for (Map.Entry<?, ?> entry : map.entrySet()) {
        kClass.cast(entry.getKey());
        vClass.cast(entry.getValue());
    }
    return (Map<K,V>) map;
}

推荐