Перевірте, чи не є нульовими булевими результатами виключення


169

У мене є такий код:

Boolean bool = null;

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

Чому моя перевірка на булеву змінну "bool" призводить до виключення? Чи не слід просто стрибати прямо повз твердження if, коли воно «бачить», що це неправда? Коли я видаляю оператор if або перевіряю, чи він НЕ нульовий, виняток відходить.


3
Наведені вище відповіді про розпакування об'єктів є правильними. Для повноти, однак, ви також можете змінити свій код, щоб використовувати примітивний "boolean" замість обгортки об'єктів "Boolean". Ви також повинні освіжити себе різницею між примітивом і Об'єктом.
Марво

Тим часом ... 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як будь-який інший об'єкт.

У вашому конкретному випадку ваше Booleanє, nullі 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. Не можу погодитися більше :)
Vinicius

402

Якщо вам не подобаються додаткові нульові перевірки:

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

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

7
@Atul Так, тут потрібні рівні рівні. Тому що (new Boolean (true) == new Boolean (true)) .... false. Причина: Boolean - це просто клас і може мати декілька примірників, як і будь-який інший клас у java.
AvrDragon

35
да, це ганьба, конструктор повинен бути приватним , так це переконатися , що це twingleton ...
Фортран

15
@fortran +1 для "twingleton".
Bennett McElwee

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
Подача виключень є непотрібною, і поруч це робиться так, що є поганим прикладом для початківців. Цього заслуговує скорочення, IMO. (Так ... я знаю, що він походить із прикладу коду, але повторення його у відповіді, як видається, підтверджує його.)
Стівен C

1
Який тоді ПРАВИЛЬНИЙ шлях? Я не бачу вашої відповіді тут.
Марво

5
Правильний спосіб - це той, що вище. Крім того, обробка винятків є занадто загальною і не рекомендує.
vellvisher

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 вказує на null, ви завжди отримаєте NullPointerException, вам потрібно спершу десь ініціалізувати змінну з ненульовим значенням, а потім змінити її.


1
Якби це було саме так, catchблок обробляв би NullPointerException. Проблема тут полягає в тому, що ОП намагається скасувати нульове посилання на примітив.
Майк Адлер

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