【问题标题】:How to solve this Java type safety warning?如何解决这个 Java 类型安全警告?
【发布时间】:2011-02-25 00:33:15
【问题描述】:
Map session = ActionContext.getContext().getSession();
session.put("user", user);

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

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 用户都面临同样的问题......有没有一个优雅的解决方案?

【问题讨论】:

    标签: java generics casting struts2


    【解决方案1】:

    我认为除了@SuppressWarnings("unchecked") 之外别无他法。我相信你可以把它放在有问题的线上方,它只会压制那条线。

    编辑:您也可以这样做Map&lt;?, ?&gt; session = ActionContext.getContext().getSession();,但我不确定您是否愿意这样做;您将无法以这种方式将任何内容放入地图中(因为编译器无法检查您所放入内容的类型),只能从中读取。

    【讨论】:

      【解决方案2】:

      最安全、最有效的处理方法可能是:

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

      然后对从会话映射中检索到的对象进行类型转换。

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

      其他更昂贵的替代品包括:

      • Map&lt;?, ?&gt; 到新的Map&lt;String, Serializable&gt; 实例的逐项复制,将键和值分别转换为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;
      }
      

      【讨论】:

        【解决方案3】:

        您使用的是哪个版本的 Struts 2(尤其是 XWork)?对我来说,您的以下代码给出了错误:

        Map<String, Serializable> session = (Map<String, Serializable>)ActionContext.getContext().getSession();
        session.put("user", user);
        
        Cannot cast from Map<String,Object> to Map<String,Serializable>.
        

        另一方面,这可以正常工作并且不会发出警告:

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

        【讨论】:

        • 我使用的是最新版本的 2.1.8.1。您的建议给出了以下警告:类型安全:类型 Map 的表达式需要未经检查的转换以符合 Map
        • struts.apache.org/2.1.8.1/struts2-core/apidocs/com/opensymphony/… 看来2.1.8.1的getSession应该返回一个参数化的map。您确定它已正确安装并且没有使用以前安装的旧版本吗?
        • @Nicolas Raoul:我们的环境有些不同,因为我没有收到警告。我仍然会检查您使用的 XWork 版本。
        • 确实,我实际上安装了两个版本,并且错误地使用了旧版本,很抱歉造成混淆,非常感谢您的帮助!
        【解决方案4】:

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

        例如

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

        将对“参数化”Map&lt;Integer, Map&gt; 发出警告。

        所以正确的格式如下:

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

        【讨论】:

          【解决方案5】:

          如果你这样做会怎样:

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

          【讨论】:

          • 它给出了另一个警告:类型安全:类型 Map 的表达式需要未经检查的转换以符合 Map
          【解决方案6】:

          按以下方式投射,

          public void setSession(Map<String, Object> sessionMap) {
          
              // TODO Auto-generated method stub
          
              this.sessionMap = (SessionMap<String, Object>) sessionMap;
          }
          

          【讨论】:

            【解决方案7】:

            只需在@GET方法的顶部写@SuppressWarnings("unchecked"),希望对你有所帮助。

            【讨论】:

              猜你喜欢
              • 2016-04-20
              • 2021-03-27
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-04-07
              • 1970-01-01
              相关资源
              最近更新 更多