2013-04-26 2 views
15

Это одно для пуристов java, я думаю. Недавно у меня возникла проблема с методом для выполнения пользовательского синтаксического анализа значений String в Boolean. Достаточно простая задача, но по каким-то причинам ниже метод был бросать NullPointerException в нулевом случае ...NullPointerException from Boolean

static Boolean parseBoolean(String s) 
{ 
    return ("1".equals(s) ? true : ("0".equals(s) ? false : null)); 
} 

Возвращаемый тип метода Boolean так, почему и как может NullPointerException быть выброшен? От отладки через это кажется, что исключение выбрасывается в том месте, где вложенный условный оператор в строке вычисляет значение null и возвращает значение null во внешнюю строку в строке, но опять-таки я не могу объяснить, почему.

В конце концов я сдался и переписал метод следующим образом, который работает, как ожидалось:

static Boolean parseBoolean(String s) 
{ 
    if ("1".equals(s)) return true; 
    if ("0".equals(s)) return false; 

    return null; 
} 

Следующий код на полпути между двумя, а также работает, как ожидалось:

static Boolean parseBoolean(String s) 
{ 
    if ("1".equals(s)) return true; 

    return "0".equals(s) ? false : null; 
} 
+2

+1 для приятного «головоломки» – NilsH

+0

@NilsH спасибо за +1 и за решение! – Robin

ответ

13

Это также работает:

static Boolean parseBoolean(String s) 
{ 
    return ("1".equals(s) ? Boolean.TRUE : ("0".equals(s) ? Boolean.FALSE : null)); 
} 

Так что причина, вы получаете NPE из-за Autoboxing, потому что использование boolean в тройном оператора приводит к тому, результат выражения следует рассматривать как boolean. И un-бокс null вызывает NPE.

+1

+1 Хорошо. Не то, что один оригинал думает, глядя на код. –

+0

Хороший ответ @ Нильс - скользкий маленький дьявол тот! Я не думал использовать константы 'Boolean'. – Robin

8

Мои предложение? Не возвращайте Boolean, возвращение boolean и бросить исключение:

static boolean parseBoolean(String s) 
{ 
    if ("1".equals(s)) return true; 
    if ("0".equals(s)) return false; 

    throw new IllegalArgumentException(s + " is not a boolean value."); 
} 

Принятие подхода, как выше поможет избежать случайно ссылки на объект нулевой Boolean.

См. excellent answer from NilsH, чтобы узнать, почему ваш оригинальный метод выбрасывает исключение.

+1

Согласен. Лучше провалиться быстрее, чем работать в NPE позже. Boolean использует его, если вам нужно решение «tri state». – NilsH

+0

Это состояние трех состояний, поэтому я действительно не должен бросать исключения для ожидаемых значений! И все-таки не обработка исключений дороже? – Robin

2

Интересно, но ответ не отвечает почему это происходит в первую очередь.

Это связано с тернарным выражением.

Компилятор интерпретирует нуль как нулевую ссылку на Boolean, применяет правила autoboxing/unboxing для Boolean (на null) => вы получаете исключение NullPointerException во время выполнения.

+2

Я думаю, вам нужно перечитать ответы;) – NilsH

+1

@NilsH, вероятно, на момент написания этой пропущенной части. :) +1 от меня. – Eugene

Смежные вопросы