Eclipse выдает предупреждение о мертвом коде для достижимого кода (вариант)

У меня есть следующий код:

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;. Удаление теста для keyValue == null также удаляет предупреждение, но я не понимаю, как этот дополнительный тест делает оператор возврата мертвым кодом. Ясно, что если карта не содержит записи для какого-то ненулевого keyValue, то rowIndex все еще может быть нулевым. Или я что-то здесь упускаю?

Я видел похожие проблемы с Eclipse (например, здесь) , но этот кажется другим и более тривиальным.


person geert3    schedule 15.10.2018    source источник
comment
Какая у вас версия Java? между Java 7 и 8 есть разница.   -  person Guy    schedule 15.10.2018
comment
У меня такое было на Java8, но предупреждение есть и на 7 и на 8.   -  person geert3    schedule 15.10.2018
comment
Также он выдает NPE в обоих случаях (см. комментарий к принятому ответу)   -  person geert3    schedule 15.10.2018


Ответы (2)


Я предполагаю, что строка 3 интерпретируется как

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

(поэтому оба аргумента ?: объединены как int) - как ни странно, Eclipse теперь не показывает предупреждений, даже если теперь очевидно, что rowIndex никогда не равен нулю...

Вы также можете заменить 0 на Integer.valueOf(0), чтобы предупреждение исчезло.

person Gyro Gearless    schedule 15.10.2018
comment
Вы правы, проблема не в Eclipse, а в моем коде. Тернарное выражение вызывает автобокс к int, поэтому, если keyValueToRowIndex.get(keyValue) возвращает null, в строке 3 выдается исключение NullPointerException. Спасибо, что указали на это. Замена 0 на Integer.valueOf(0) решает проблему. - person geert3; 15.10.2018

Короткий (удивительный) ответ: Затмение верно! Это мертвый код!

Причина

Важной частью является тернарное выражение в следующей строке кода:

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

В спецификации языка Java (JLS) говорится о "Условный оператор?", если первое выражение имеет тип int , а второе выражение имеет тип Integer, тип всего выражения будет int.

В вашем случае первое выражение представляет собой постоянное буквальное значение 0, которое равно int. Второе выражение является результатом метода get, который возвращает объект типа Integer. Итак, согласно JLS, все выражение имеет примитивный тип int!

Это означает, что если будет оцениваться второе выражение (вызов get), результат будет распакован с Integer на int. Затем это значение int будет снова автоматически упаковано в Integer, чтобы его можно было присвоить левому операнду rowIndex.

Но что произойдет, если карта вернет значение null? В этом случае распаковка с Integer на int невозможна, и будет выброшен NullPointerExpression!

Итак, затмение верно, поскольку ваше выражение никогда не может вернуть null, rowIndex также никогда не будет null, а блок then вашего оператора if никогда не будет выполнен и, следовательно, является мертвым кодом!

Решение

Решение простое: используйте объект Integer вместо примитивного значения int для вашего первого выражения:

Integer rowIndex = (keyValue == null) ? Integer.valueOf(0) : keyValueToRowIndex.get(keyValue);
person isnot2bad    schedule 15.10.2018
comment
спасибо, да, это полный ответ. Я уже понял это из ответа @Gyro Gearless и принял это. +1 за ссылки. - person geert3; 15.10.2018