Eclipse 为可访问的代码(变体)提供死代码警告

Eclipse gives dead code warning for reachable code (variant)

我有以下代码:

public String myMethod(String keyValue) {
    Map<String, Integer> keyValueToRowIndex = ...
    Integer rowIndex = (keyValue == null) ? 0 : keyValueToRowIndex.get(keyValue);
    if (rowIndex == null)
      return null;
    ...
}

Eclipse 在 return null; 上发出 "dead code" 警告。删除 keyValue == null 的测试也会删除警告,但我看不到额外的测试如何使 return 语句成为死代码。显然,如果映射不包含某些非空 keyValue 的条目,那么 rowIndex 仍然可以为空。还是我在这里遗漏了什么?

我见过类似的 Eclipse 问题(例如 ),但这个问题似乎不同且更微不足道。

我的猜测是第 3 行被解释为

Integer rowIndex = Integer.valueOf((keyValue == null) ? 0 : keyValueToRowIndex.get(keyValue).intValue());

(所以 ?: 的两个参数统一为 int)- 奇怪的是,Eclipse 现在没有显示任何警告,即使现在很明显 rowIndex 永远不会为空...

您也可以将 0 替换为 Integer.valueOf(0) 以使警告消失。

(令人惊讶的)简短回答:Eclipse 是正确的!这是死代码!

原因

重要的部分是下面这行代码中的三元表达式:

    Integer rowIndex = (keyValue == null) ? 0 : keyValueToRowIndex.get(keyValue);

Java language specification (JLS) says about the "Conditional Operator ?",即如果第一个表达式的类型为int,第二个表达式的类型为Integer,则整个表达式的类型为int.

在你的例子中,第一个表达式是常量文字值 0,它是一个 int。第二个表达式是 get 方法的结果,它 return 是一个 Integer 类型的对象。所以根据 JLS,整个表达式具有原始类型 int!

这意味着,如果对第二个表达式(get 调用)进行求值,结果将从 Integer 拆箱到 int。然后,此 int 值将再次自动装箱到 Integer 中,以便能够将其分配给左操作数 rowIndex.

但是,如果映射 return 是一个 null 值,会发生什么?在这种情况下,从Integerint的拆箱是不可能的,会抛出一个NullPointerExpression

所以 eclipse 是正确的,因为你的表达式永远不会 return nullrowIndex 也永远不会是 null 并且你的 if 语句的 then-block永远不会被执行,因此是死代码!

解决方案

解决方案很简单:为第一个表达式使用 Integer 对象而不是原始 int 值:

Integer rowIndex = (keyValue == null) ? Integer.valueOf(0) : keyValueToRowIndex.get(keyValue);