Проверьте, имеет ли значение 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.