Boolean vs boolean in Java

198

Есть дискуссии вокруг Integerпротив intJava. Значением по умолчанию первого является nullвремя, в то время как во втором оно 0. Как насчет Booleanпротив boolean?

Переменная в моем приложении может иметь 0/ 1значения. Я хотел бы использовать boolean/ Booleanи предпочитаю не использовать int. Могу ли я использовать Boolean/ booleanвместо?

Ниль
источник
2
По причинам, связанным с проектированием системы, я бы выбрал Boolean, поскольку у него есть опция «Пользователь еще не определился», который не равен ни «true», ни «false». Я бы использовал логический примитив только в том случае, если я уверен на 100%, что истинных / ложных опций достаточно. В базе данных опция NULL обычно доступна без проблем (или просто снимая ограничения NOT NULL для последующего запроса)
CsBalazsHungary
2
Точная копия В чем разница между логическим и логическим в Java? (потому что GWT не имеет значения).
Дан Даскалеску

Ответы:

273

Да, вы можете использовать Boolean/ booleanвместо.

Первый объект Object, а второй тип примитив.

  • На первом вы получите больше методов, которые будут полезны.

  • Второй дешевый, учитывая затраты памяти . Второй сэкономит вам больше памяти, так что дерзайте

Теперь выберите свой путь.

Джигар Джоши
источник
70
Вы могли бы сформулировать это как «второе сэкономит вам гораздо больше памяти, так что дерзайте». Полезные методы в Boolean в большинстве случаев могут быть вызваны без его экземпляра.
DJClayworth
3
Пока вы используете вместо Boolean.valueOf (значение) нового Boolean (значение), память не должна быть проблемой.
Грег Кейс
2
для AsyncTask, вы можете использовать только Booleanвместо boolean.
Raptor
99
Следует отметить булева на самом деле имеет 3 состояние ... true, falseи nullгде булева имеет логическое 2 состояния ( trueа false)
respectTheCode
14
Boolean является трилловым :)
Topera
50

Boolean оборачивает логический примитивный тип. В JDK 5 и более поздних версиях Oracle (или Sun до того, как Oracle их купил) ввела автобокс / распаковку , что по сути позволяет вам это делать

boolean result = Boolean.TRUE;

или

Boolean result = true; 

Что по сути делает компилятор,

Boolean result = Boolean.valueOf(true);

Итак, для вашего ответа, это да.

Бухаке синди
источник
4
Примечание: вы не всегда можете безопасно назначить Booleana boolean. Если Booleanэто так, nullи вы пытаетесь назначить его для a boolean, он выдаст NullPointerExceptionво время выполнения.
Дункан Лук
если Booleanкласс, то почему значение всегда ложно, даже если я изменил значение из другого класса, ссылающегося на ту же логическую переменную? Какой смысл в этом, Booleanесли мы не можем ссылаться на разные классы экземпляров / передавать в качестве аргумента?
user924
нашел ответ, мы можем использовать AtomicBooleanи ссылаться на него из различий классов
user924
35

Я немного расширяю предоставленные ответы (поскольку до сих пор они концентрируются на своей «собственной» / искусственной терминологии, сосредотачиваясь на программировании на конкретном языке, вместо того, чтобы позаботиться о более широкой картине за кулисами создания языков программирования в целом, то есть когда что-то происходит как соображения безопасности типа и памяти имеют значение):

Int не булево

Рассматривать

    boolean bar = true;      
    System.out.printf("Bar is %b\n", bar);
    System.out.printf("Bar is %d\n", (bar)?1:0);
    int baz = 1;       
    System.out.printf("Baz is %d\n", baz);
    System.out.printf("Baz is %b\n", baz);

с выходом

    Bar is true
    Bar is 1
    Baz is 1
    Baz is true

Код Java в третьей строке (bar)?1:0показывает, что bar ( логическое значение ) не может быть неявно преобразовано (приведено) в int . Я говорю об этом не для того, чтобы проиллюстрировать детали реализации JVM, а чтобы подчеркнуть, что с точки зрения низкого уровня (как объем памяти) нужно отдавать предпочтение значениям над безопасностью типов. Особенно, если безопасность этого типа не используется полностью / полностью, как в булевых типах, где проверки выполняются в форме

если значение \ in {0,1} затем приведено к логическому типу, в противном случае выдается исключение.

Все только для того, чтобы заявить, что {0,1} <{-2 ^ 31, .., 2 ^ 31 -1}. Похоже на излишество, верно? Безопасность типов действительно важна для пользовательских типов, а не для неявного приведения примитивов (хотя последние включены в первый).

Байты не являются типами или битами

Обратите внимание, что в памяти ваша переменная из диапазона {0,1} будет по-прежнему занимать как минимум байт или слово (xbit в зависимости от размера регистра), если специально не позаботиться об этом (например, красиво упаковано в памяти - 8 «логическое значение») биты в 1 байт - туда и обратно).

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

ключевое слово против типа

Наконец, ваш вопрос о сравнении ключевого слова и типа . Я считаю, что важно объяснить, почему или как именно вы будете получать производительность, используя / предпочитая ключевые слова («помеченные» как примитивные ), а не типы (обычные составные определяемые пользователем классы, использующие другой класс ключевых слов ) или другими словами

boolean foo = true;

против

Boolean foo = true;

Первая «вещь» (тип) не может быть расширена (подкласса) и не без причины. По сути, терминология Java для классов примитивов и оберток может быть просто переведена во встроенное значение (LITERAL или константа, которая напрямую подставляется компилятором всякий раз, когда возможно вывести подстановку, или, если нет, - все равно возвращается к переносу значения).

Оптимизация достигается за счет тривиального:

"Меньше операций приведения во время выполнения => больше скорости."

Вот почему, когда фактический вывод типа сделан, он может (все еще) закончиться созданием экземпляра класса-оболочки со всей информацией о типе, если это необходимо (или преобразованием / приведением к такому типу).

Таким образом, разница между логическим и логическим типом заключается именно в компиляции и во время выполнения (немного далеко, но почти как instanceof против getClass () ).

Наконец, автобокс медленнее, чем примитивы

Обратите внимание на тот факт, что Java может делать автобокс только как «синтаксический сахар». Это ничего не ускоряет, просто позволяет писать меньше кода. Вот и все. Приведение и упаковка в контейнер информации о типе все еще выполняется. По соображениям производительности выбирайте арифметику, которая всегда будет пропускать дополнительные операции по созданию экземпляров классов с информацией о типах для реализации безопасности типов. Отсутствие безопасности типа - это цена, которую вы платите за повышение производительности. Для кода с булевозначными выражениями безопасность типа (когда вы пишете меньше и, следовательно, неявный код) будет иметь решающее значение, например, для управления потоками if-then-else.

Евгений Якимович
источник
16

Вы можете использовать логические константы - Boolean.TRUEи Boolean.FALSEвместо 0и 1. Вы можете создать свою переменную типа, booleanесли примитив - это то, что вам нужно. Таким образом, вам не придется создавать новые Booleanобъекты.

Холодные бобы
источник
4

Одно наблюдение: (хотя это можно думать о побочном эффекте)

логическое бытие примитива может сказать да или нет.

Логический объект - это объект (он может ссылаться на «да» или «нет» или «не знаю», т. Е. На ноль)

Судип Бхандари
источник
3

В основном, логические значения представляют примитивный тип данных, где логические значения представляют ссылочный тип данных. эта история начинается, когда Java хочет стать чисто объектно-ориентированной, она предоставляет концепцию класса-оболочки, чтобы не использовать примитивный тип данных.

boolean b1;
Boolean b2;

b1и b2не такие же.

Сачин Джадхав
источник
1

Вы можете использовать Boolean / Boolean. Простота - это путь. Если вам не нужны конкретные API (коллекции, потоки и т. Д.), И вы не предвидите, что они вам понадобятся - используйте его примитивную версию (булево).

  1. С примитивами вы гарантируете, что не будете передавать нулевые значения.
    Вы не попадете в такие ловушки. Приведенный ниже код генерирует исключение NullPointerException (из: Booleans, условные операторы и автобокс ):

    public static void main(String[] args) throws Exception { Boolean b = true ? returnsNull() : false; // NPE on this line. System.out.println(b); } public static Boolean returnsNull() { return null; }

  2. Используйте Boolean, когда вам нужен объект, например:

    • Поток логических значений,
    • По желанию
    • Коллекции Булевых
Витольд Качурба
источник