Я недавно обнаружил необычную ошибку в своем коде в ходе случайного специального тестирования. Итак, я сделал для него тестовый пример.
Вот мой тестовый пример:
SampleRequest request = new SampleRequest();
request.setA(null);
request.setB(null);
assertEquals(null, request.getAOrB());
A и B определены как типы java.lang.Integer и имеют прямые методы установки для установки своих значений в запрос.
Также есть перечисление. Он имеет примитивное целочисленное значение и метод, который используется в этом коде. Я размещу здесь соответствующие фрагменты:
enum Swapper {
public int c;
Swapper findSwapperToUse(final int a) {
for(Swapper swapper : values()) {
if(swapper.c == a) {
return swapper;
}
}
return null;
}
}
Вот метод, который сбивает с толку. Вызов тестового метода для этого метода приводит к NPE, но в последней строке метода.
public class SampleRequest {
private Integer A;
private Integer B;
public void setA(final Integer A) {
this.A = A;
}
public void setB(final Integer B) {
this.B = B;
}
public Integer getAOrB() {
return A != null ? Swapper.findSwapperToUse(A).c
: B;
}
}
В тесте для A и B установлено значение NULL. Следовательно, A! = Null возвращает false. Однако я получаю исключение NullPointerException в номере строки для строки: B.
Я предполагаю, что по какой-то причине оценивается первое выражение Swapper.findSwapperToUse (A) .c, и поэтому A.intValue ( ) вызывается через автобоксирование, в результате чего возникает исключение NullPointerException для нулевого значения. В процессе отладки известно, что findSwapperToUse () не вызывается.
Однако, согласно этому вопросу, этого не должно происходить: оба A и B имеют значение null. Следовательно, A! = Null возвращает false. Однако я получаю исключение NullPointerException в номере строки для строки: B.
Я предполагаю, что по какой-то причине оценивается первое выражение Swapper.findSwapperToUse (A) .c, и поэтому A.intValue ( ) вызывается через автобоксирование, в результате чего возникает исключение NullPointerException для нулевого значения. В процессе отладки известно, что findSwapperToUse () не вызывается.
Однако, согласно этому вопросу, этого не должно происходить: оба A и B имеют значение null. Следовательно, A! = Null возвращает false. Однако я получаю исключение NullPointerException в номере строки для строки: B.
Я предполагаю, что по какой-то причине оценивается первое выражение Swapper.findSwapperToUse (A) .c, и поэтому A.intValue ( ) вызывается через автобоксирование, в результате чего возникает исключение NullPointerException для нулевого значения. В процессе отладки известно, что findSwapperToUse () не вызывается.
Однако, согласно этому вопросу, этого не должно происходить: Тернарное вычисление Java (немедленное выполнение)
Невыбранное выражение операнда не оценивается для данной конкретной оценки условного выражения.
Возврат значения NULL (B) не приведет к исключению NullPointerException - это прекрасно, если вернуть здесь нулевой результат.
Что, черт возьми, происходит?
РЕДАКТИРОВАТЬ: Я забыл добавить, что я изменил код, чтобы избежать этого, используя прямой оператор if - следующий код работает должным образом:
public Integer getAOrB() {
if(A != null) {
return Swapper.findSwapperToUse(A).c;
}
return B;
}