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
值,会发生什么?在这种情况下,从Integer
到int
的拆箱是不可能的,会抛出一个NullPointerExpression
!
所以 eclipse 是正确的,因为你的表达式永远不会 return null
,rowIndex
也永远不会是 null
并且你的 if 语句的 then-block永远不会被执行,因此是死代码!
解决方案
解决方案很简单:为第一个表达式使用 Integer
对象而不是原始 int
值:
Integer rowIndex = (keyValue == null) ? Integer.valueOf(0) : keyValueToRowIndex.get(keyValue);
我有以下代码:
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
值,会发生什么?在这种情况下,从Integer
到int
的拆箱是不可能的,会抛出一个NullPointerExpression
!
所以 eclipse 是正确的,因为你的表达式永远不会 return null
,rowIndex
也永远不会是 null
并且你的 if 语句的 then-block永远不会被执行,因此是死代码!
解决方案
解决方案很简单:为第一个表达式使用 Integer
对象而不是原始 int
值:
Integer rowIndex = (keyValue == null) ? Integer.valueOf(0) : keyValueToRowIndex.get(keyValue);