【问题标题】:Run time type checking and casting in javajava中的运行时类型检查和强制转换
【发布时间】:2014-10-19 21:24:47
【问题描述】:

我有一个字符串和对象的映射,并且我从外部源获取此映射,对于特定场景,我将此对象作为

"ArrayList<LinkedHashMap<String, Double>>"

ArrayList<LinkedHashMap<String, Double>> targetDetailContainer = null;
Map<String, Object> confData = getConfData();
if (confData.containsKey("Target-Details")) {
    targetDetailContainer = (ArrayList<LinkedHashMap<String, Double>>) confData
            .get((Object) "Target-Details");
}

现在在我将对象投射到的最后一行

"ArrayList<LinkedHashMap<String, Double>>"

我收到警告 -

类型安全:从对象到未经检查的强制转换

"ArrayList<LinkedHashMap<String, Double>>"

我曾尝试在投射之前进行类型检查,类似这样,

if (confData.containsKey("Target-Details")
    && confData.get((Object) "Target-Details") instanceof ArrayList<?>) {
targetDetailContainer = (ArrayList<LinkedHashMap<String, Double>>) confData
        .get((Object) "Target-Details");
}

但它没有奏效。请提出一些建议,我怎样才能摆脱这个警告。

【问题讨论】:

  • 每当编译器无法确定对象的类型时,就会出现警告。通过使用@SuppressedWarnings(“未选中”),您是在告诉编译器“我知道我在做什么,我不需要你的建议。所以请关闭up"。那么责任就完全在你身上了

标签: java arraylist casting warnings typechecking


【解决方案1】:

自从编译时检查抱怨你从ObjectArrayList&lt;LinkedHashMap&lt;String, Double&gt;&gt; 的转换后,你几乎什么也做不了。只需将注解 @SuppressWarnings("unchecked") 放在您的方法之前。

【讨论】:

    【解决方案2】:

    警告将作为编译类型检查的一部分存在,该检查将超类型的对象转换为特定类型的对象。这是编译器告诉您的方式。

    “嘿,我不能确定你正在转换的对象是否是 ArrayList&lt;LinkedHashMap&lt;String, Double&gt;&gt; 的对象,当你将此对象视为这种类型时,请为 RuntimeExceptions 做好准备。所以从现在开始,你就是靠你自己。”

    如果你只想摆脱这个异常并且你已经为可能发生的任何 RuntimeException 做好准备,请继续并用 @SuppressedWarning ("unchecked") 标记它。但我建议你做一些防御机制并编辑你这样编码

        ArrayList<LinkedHashMap<String, Double>> targetDetailContainer = null;
        Map<String, Object> confData = getConfData();
    
        if (confData.containsKey("Target-Details")) {
    
            Object value = confData.get("Target-Details");
            if (value instanceof ArrayList<?>) {
                ArrayList temp = (ArrayList) value;
                for (Object vals : temp) {
                    boolean flag = false;
                    if (vals instanceof LinkedHashMap<?, ?>) {
                        LinkedHashMap<?, ?> map = (LinkedHashMap) vals;
                        for (Map.Entry entry : map.entrySet()) {
                            if (entry.getKey() instanceof String
                                    && entry.getValue() instanceof Double) {
                                flag = true;
                            }
    
                            if (!flag) {
                                throw new RuntimeException(
                                        "Objects are of different types");
                            }
    
                        }
    
                    }
                    targetDetailContainer = (ArrayList<LinkedHashMap<String, Double>>) confData
                            .get((Object) "Target-Details");
                }
    
            }
        }
    

    由于检查量很大,编译器无法为您确定,它会给您未检查的警告

    【讨论】:

      【解决方案3】:

      confData.get((Object) "Target-Details" 的返回值存储在一个对象中,然后键入检查该对象以删除警告。

      由于您两次调用 confData.get((Object) "Target-Details",它会将它们视为两个不同的对象,一个是您进行类型检查的对象,一个是您没有进行类型检查的对象。

      应该是这样的:

      Object temp = confData
          .get((Object) "Target-Details");
      
      
      if (confData.containsKey("Target-Details")
      && temp instanceof ArrayList<?>) {
      targetDetailContainer = (ArrayList<LinkedHashMap<String, Double>>) temp;
      }
      

      上面的代码可能有错别字,因为我是通过移动应用程序输入的,但概念是使用临时对象。

      应避免抑制警告,因为这是不可取的,并且会对代码质量产生负面影响。

      【讨论】:

      • 没错,但代码只是为了摆脱表明 Java 缺陷的警告,在我看来也不是最好的解决方案。它也应该使用反射来实现,但有一个问题 - 为什么有人想要这样做?
      • 临时变量在方法范围之外被删除。这不是Java的“错误”,如果你调用了两次getter方法,任何语言的编译器怎么能知道第一次getter调用的返回值在第二次调用getter时已经过类型检查?这与 Java 泛型或语言设计@Lucas 无关。
      • temp 变量不会消除警告,因为仍然无法验证强制转换中的类型参数。反射在这里没有帮助,因为信息在运行时根本不可用。这就是警告告诉程序员无法检查类型的原因。
      • 是的,实际上即使是上述解决方案中提到的 temp 类型检查也对我不起作用。这个问题的目的是避免错误的转换和异常,因为数据来自外部来源,因此对数据没有太多控制
      【解决方案4】:

      你可以添加

      @SuppressWarnings("unchecked")
      

      在您禁止此警告的方法之前。

      【讨论】:

        【解决方案5】:

        我建议使用@SuppressedWarnings ("unchecked") 注释,因为您对此警告无能为力。这不是很有害,但是由于类型擦除和编译时缺少类型信息(对于泛型类型),您实际上无法做任何其他事情。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-24
          • 2015-06-20
          • 2019-09-13
          相关资源
          最近更新 更多