Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eclipse gives dead code warning for reachable code (variant)

I have following code:

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

Eclipse gives a "dead code" warning on the return null;. Removing the test for keyValue == null also removes the warning but I don't see how that extra test makes the return statement dead code. Clearly if the map contains no entry for some non-null keyValue, then rowIndex can still be null. Or am I missing something here?

I've seen similar Eclipse issues (here for instance), but this one seems a different and more trivial one.

like image 606
geert3 Avatar asked Oct 15 '18 10:10

geert3


2 Answers

The (surprising) short answer: Eclipse is right! This is dead code!

Reason

The important part is the ternary expression in the following line of code:

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

The Java language specification (JLS) says about the "Conditional Operator ?", that, if the first expression is of type int, and the second expression is of type Integer, the type of the entire expression will be int.

In your case, the first expression is the constant literal value 0, which is an int. The second expression is the result of the get method, which returns an object of type Integer. So according to the JLS, the entire expression has primitive type int!

This means, if the second expression (the get-call) will be evaluated, the result will be unboxed from Integer to int. This int value will then be auto-boxed again into an Integer to be able to assign it to the left operand, rowIndex.

But what happens, if the map returns a null value? In this case, unboxing from Integer to int is not possible, and a NullPointerExpression will be thrown!

So eclipse is right, as your expression can never return null, rowIndex will never be null either and the then-block of your if-statement will never be executed and hence is dead code!

Solution

The solution is simple: Use an Integer object instead of an primitive int value for your first expression:

Integer rowIndex = (keyValue == null) ? Integer.valueOf(0) : keyValueToRowIndex.get(keyValue);
like image 79
isnot2bad Avatar answered Oct 13 '22 18:10

isnot2bad


My guess is that line 3 is interpreted as

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

(so both arguments to ?: are unified as int) - oddly enogh, Eclipse now shows no warning, even if it is now obvious that rowIndex is never null...

You might also replace the 0 with Integer.valueOf(0) to make the warning disappear.

like image 36
Gyro Gearless Avatar answered Oct 13 '22 18:10

Gyro Gearless