关于泛型:如何解决这种Java类型的安全警告?

How to solve this Java type safety warning?

1
2
Map session = ActionContext.getContext().getSession();
session.put("user", user);

此代码生成一个警告:类型安全:方法Put(对象、对象)属于原始类型映射。对泛型类型map的引用应参数化。

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

此代码生成警告:type safety:unchecked cast from map to map

getsession方法属于struts2,因此我无法修改它。我希望避免使用@suppresswarnings,因为其他警告可能有用。

我想世界上所有的struts2用户都面临着同样的问题…有优雅的解决方案吗?


我认为除了@suppresswarnings("unchecked")没有其他方法。我相信你可以把它放在问题的线的正上方,它只会抑制那条线。

编辑:你也可以做Map session = ActionContext.getContext().getSession();,但我不确定你有多愿意这样做;你不能用这种方式把任何东西放到地图中(因为编译器不能检查你要放的东西的类型),只能从中读取。


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

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

然后键入cast从会话映射中检索到的对象。

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

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

  • Map到新Map实例的逐条复制,将密钥和值分别转换为StringSerializable,或

  • 像下面这样安全地执行类型转换的一般方法。

1
2
3
4
5
6
7
8
@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;
}


它请求您参数化该值,如果该值需要参数,则传递它们。

例如

1
Map<Integer, Map> vCombinedCodeMap = new HashMap<>();

将对"参数化"Map发出警告。

因此正确的格式如下:

1
Map<Integer, Map<String, String>> vCombinedCodeMap = new HashMap<>();

您使用的是什么版本的Struts2(特别是XWork)?对于我来说,您的以下代码给出了一个错误:

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

Cannot cast from Map<String,Object> to Map<String,Serializable>.

另一方面,这是有效的,没有警告:

1
Map<String, Object> session = ActionContext.getContext().getSession();


只需在@GET方法的顶部编写@SuppressWarnings("unchecked"),希望它能帮助您。


铸造如下:

1
2
3
4
5
6
public void setSession(Map<String, Object> sessionMap) {

    // TODO Auto-generated method stub

    this.sessionMap = (SessionMap<String, Object>) sessionMap;
}


如果你这样做会怎么样:

1
Map<String, Serializable> session = ActionContext.getContext().getSession();