Проверьте, имеет ли значение null Boolean значение true, приводит к исключению


169

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

Boolean bool = null;

try 
{
    if (bool)
    {
        //DoSomething
    }                   
} 
catch (Exception e) 
{
    System.out.println(e.getMessage());             
}

Почему моя проверка на булеву переменную "bool" приводит к исключению? Разве он не должен просто перепрыгнуть через оператор if, когда «видит», что это неправда? Когда я удаляю оператор if или проверяю, не является ли он нулевым, исключение исчезает.


3
Ответы выше о распаковке объектов верны. Для полноты картины, однако, вы также можете изменить свой код, чтобы использовать примитив «логический» вместо обёртки объекта «Логический». Вам также следует освежить в себе разницу между примитивом и объектом.
Марво

Между тем ... if (bool == Boolean.TRUE)оценивает false без генерации исключения. Не уверен, было ли это намеренно в случае, который я только что нашел.
simon.watts

2
@ simon.watts, который был бы ложным для boolтого, чтобы быть nullИЛИ, если Booleanбыл построен явно (а не как ссылка Boolean.TRUE). Так что не рекомендуется; в отличие от того, if (Boolean.TRUE.equals(bool))который будет работать, как ожидалось, в том числе безопасно обрабатывать nullстоимость.
StaxMan

Ответы:


171

Когда у вас есть, booleanэто может быть trueили false. Тем не менее, когда у вас есть, Booleanэто может быть либо Boolean.TRUE, Boolean.FALSEлибо nullкак любой другой объект.

В вашем конкретном случае, оператор Booleanis nullи is ifзапускает неявное преобразование в booleanто, что производит NullPointerException. Вам может понадобиться вместо этого:

if(bool != null && bool) { ... }

23
Технически, это Booleanможет быть любое количество истинных примеров, а не просто Boolean.TRUE. Например new Boolean(true).
Стив Куо

1
Я изо всех сил пытаюсь понять, почему if (myBoolean)(где myBooleanэто Boolean) не вызывает ошибку компилятора или, по крайней мере, предупреждение. Это гоча точно.
Джош М.

1
@JoshM. Это происходит потому , что Java делает бокс и распаковка оберток: docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Vinicius

3
@Vinicius уверен, но в этом случае компилятор должен либо сделать для нас нулевое значение, по крайней мере, через предупреждение компилятора.
Джош М.

2
@JoshM. Больше не могу согласиться :)
Виниций

402

Если вам не нравятся дополнительные нулевые проверки:

if (Boolean.TRUE.equals(value)) {...}

1
@AvrDragon: равно ли требуется? Оператор == работает здесь, так как логическое значение имеет только два значения
Atul

7
@ Атул Да, здесь нужно равное. Потому что (new Boolean (true) == new Boolean (true)) равно .... false. Причина: Boolean - это просто класс, который может иметь несколько экземпляров, как и любой другой класс в Java.
AvrDragon

35
да, это позор, конструктор должен быть частным, так что это гарантировано, что это twingleton ...
Fortran

15
@fortran +1 для "twingleton".
Беннет МакЭлви

1
Нет абсолютно никакого смысла в использовании Apache BooleanUtils над этой идиомой.
StaxMan

82

Используйте Apache BooleanUtils .

(Если пиковая производительность является наиболее важным приоритетом в вашем проекте, посмотрите на один из других ответов для нативного решения, которое не требует включения внешней библиотеки.)

Не изобретай велосипед. Используйте то, что уже было построено и используйте isTrue():

BooleanUtils.isTrue( bool );

Проверяет, является ли Booleanзначение истинным, обрабатывает nullпутем возврата false.

Если вы не ограничены библиотеками, которые вам «разрешено» включать, есть множество отличных вспомогательных функций для всех видов сценариев использования, включая Booleansи Strings. Я предлагаю вам просмотреть различные библиотеки Apache и посмотреть, что они уже предлагают.


59
Изобретать колесо не так уж и плохо, когда альтернатива использует внешнюю библиотеку для чего-то столь же простого, как это.
Пол Манта

3
@PaulManta Я согласен, если это единственное, что вы когда- либо использовали в библиотеках Apache Utils, но предлагаемая идея состоит в том, чтобы «просмотреть» библиотеки, чтобы подвергнуть себя другим полезным функциям.
Джошуа Пинтер

1
Использование этих библиотек снижает производительность. Поэтому для таких базовых вещей, которые являются частью языка, вы не должны использовать библиотеки.
ACV

6
Эта библиотека заново изобретает колесо. Я стараюсь избегать таких библиотек, насколько это возможно.
mschonaker

3
@mschonaker Если Apache BooleanUtils заново изобретает колесо, что это за оригинальное колесо? Идея состоит в том, чтобы избежать создания множества вспомогательных функций, которые имитируют то, что уже было сделано в таких библиотеках, как эта. Я также использую toStringYesNoиз этой библиотеки во всех моих приложениях.
Джошуа Пинтер

13

Booleanтипы могут быть null. Вы должны сделать nullпроверку, как вы установили его null.

if (bool != null && bool)
{
  //DoSomething
}                   

3
Что не так с этим ответом? Это не проверка bool, которая будет выбрасывать исключение. Ненужные отрицательные голоса.
додексаэдр

2
Я согласен, что это вполне разумный ответ. Вы можете избавиться от обработки исключений, хотя.
Марво

14
Передача исключений не нужна, и кроме того, это делается таким образом, что это плохой пример для начинающих. Это заслуживает отрицательного ответа, ИМО. (Да ... Я знаю, что это происходит из примера кода, но повторение его в Ответе, кажется, подтверждает его.)
Стивен C

1
Что тогда правильно? Я не вижу вашего ответа здесь.
Марво

5
Правильный путь - тот, что выше ... нет обработки исключений. Кроме того, обработка исключений является слишком общей и не рекомендуется.
Веллвишер

8

Или с силой Java 8 Необязательно, вы также можете сделать такой трюк:

Optional.ofNullable(boolValue).orElse(false)

:)


5

Boolean - это класс обёртки объекта для примитивного логического значения. Этот класс, как и любой класс, действительно может быть нулевым. Из соображений производительности и памяти всегда лучше использовать примитив.

Классы-обертки в Java API служат двум основным целям:

  1. Обеспечить механизм «обертывания» значений примитивов в объекте, чтобы примитивы могли быть включены в действия, зарезервированные для объектов, например, добавленные в Коллекции, или возвращенные из метода с возвращаемым значением объекта.
  2. Предоставить ассортимент служебных функций для примитивов. Большинство из этих функций связаны с различными преобразованиями: преобразованием примитивов в и из объектов String и преобразованием примитивов и объектов String в и из различных основ (или основ), таких как двоичные, восьмеричные и шестнадцатеричные.

http://en.wikipedia.org/wiki/Primitive_wrapper_class


0

так как ваша переменная bool указывает на нуль, вы всегда получите исключение NullPointerException, вам нужно сначала инициализировать переменную где-нибудь с ненулевым значением, а затем изменить его.


1
Если бы это было просто, catchблок обработал бы исключение NullPointerException. Проблема здесь в том, что OP пытается распаковать нулевую ссылку в примитив.
Майк Адлер

«Вы будете всегда» - не всегда, за исключением примера, упрощенного кода, который ничего не делает между инициализацией переменной nullи ее тестированием. Предположительно реальный код не был бы таким простым, или весь ifтест можно было бы удалить.
nnnnnn
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.