Недавно я обнаружил необычную ошибку в моем коде в ходе случайного специального тестирования. Итак, я сделал тестовый пример для него.
Вот мой тестовый пример:
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;
}
}
Теперь вот метод, который вводит в заблуждение. Вызов метода test для этого метода приводит к 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 устанавливаются в ноль. Следовательно, A! = Null возвращает false. Тем не менее, я получаю исключение NullPointerException по номеру строки для строки: B.
Я предполагаю, что по какой-то причине первое выражение, Swapper.findSwapperToUse (A) .c, оценивается, и поэтому A.intValue () вызывается через автобокс, что приводит к исключению NullPointerException для нулевого значения. Благодаря отладке известно, что findSwapperToUse () не вызывается.
Однако по этому вопросу этого не должно происходить:
Java троичная (немедленное if) оценка
Не выбранное выражение операнда не оценивается для этой конкретной оценки условного выражения.
Возврат значения null (B) не приведет к исключению NullPointerException - здесь совершенно нормально возвращать нулевой результат.
Что, черт возьми, происходит?
РЕДАКТИРОВАТЬ: я забыл добавить, что я изменил код, чтобы избежать этого с помощью прямого оператора if - следующий код работает как ожидалось:
public Integer getAOrB() {
if(A != null) {
return Swapper.findSwapperToUse(A).c;
}
return B;
}