Почему делает автоупаковку в Java, позволяют мне иметь 3 возможных значения для булевской переменной?

Ссылка: http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html

"Если Ваша программа попытается автораспаковать пустой указатель, то она бросит NullPointerException".

javac даст Вам ошибку времени компиляции, при попытке присвоить пустой указатель булевской переменной. имеет смысл. присвоение пустого указателя к булевской переменной является a-ok., также имеет смысл, я предполагаю.

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

в течение долгого времени я был поклонником автоупаковки в java1.5 +, потому что я думал, что это заставило Java ближе быть действительно объектно-ориентированным. но, после столкновения с этой проблемой вчера вечером, я должен сказать, что думаю, что это сосет. компилятор, дающий мне ошибка, когда я пытаюсь сделать материал с неинициализированным примитивом, является хорошей вещью. Я не хочу использовать автоупаковку, если я теряю это.

Я думаю, что могу неправильно понимать точку автоупаковки, но в то же время я никогда не буду признавать, что булевская переменная должна смочь иметь 3 значения. кто-либо может объяснить это? что я не получаю?

7
задан jasonmp85 28 May 2010 в 08:48
поделиться

9 ответов

Типы в штучной упаковке - это ссылочные типы, и все ссылочные типы, примитивные блоки или нет, могут ссылаться на null . Вот почему логическое значение может относиться к null . То же самое можно сказать и о Integer . То же самое можно сказать о String и т. Д.

Типы в штучной упаковке не предназначены для того, чтобы сделать Java действительно объектно-ориентированным. Java никогда никогда не будет чисто объектно-ориентированным языком, и вам не следует кодировать так, как будто это так. Примитивные типы никогда не исчезнут, и на самом деле им следует отдавать предпочтение всякий раз, когда есть выбор.

Вот цитата из Эффективное Java 2-е издание, Правило 49: Предпочитайте примитивные типы примитивам в штучной упаковке (выделено автором):

Таким образом, используйте примитивы вместо примитивов в штучной упаковке всякий раз, когда у вас есть выбор. Примитивные типы проще и быстрее. Если вы должны использовать примитивы в штучной упаковке, будьте осторожны! Автобокс снижает многословие, но не снижает опасность использования упакованных примитивов . Когда ваша программа сравнивает два упакованных примитива с оператором == , она выполняет сравнение идентичности, что почти наверняка не то, что вы хотите. Когда ваша программа выполняет вычисления смешанного типа с использованием упакованных и распакованных примитивов, она выполняет распаковку, и , когда ваша программа выполняет распаковку, она может выбросить NullPointerException . Наконец, когда ваша программа упаковывает примитивные значения, это может привести к созданию дорогостоящих и ненужных объектов.

16
ответ дан 6 December 2019 в 05:42
поделиться

В дополнение ко всему, что здесь сказано, есть случаи, когда вы очень хотели бы иметь третье значение для логических значений - случай «необязательного» свойства.

Мы обычно сталкиваемся с этим в базах данных, с логическими столбцами, которые допускают значения NULL. Без использования логических значений нам нужно будет использовать две отдельные переменные, одна из которых указывает значение, а другая - допустимо ли оно.

На самом деле, если вы посмотрите на JDBC API, вы можете увидеть пример этой проблемы, где столбцы получают значение по умолчанию, если они равны нулю (например, 0 для числовых полей), а затем вы должны вызвать " wasNull ", чтобы проверить, является ли это истинным 0 или ложным нулем!

5
ответ дан 6 December 2019 в 05:42
поделиться

С введением автобокса никогда не предполагалось, что он заменит примитивы. В большинстве случаев примитивы - это то, что вам нужно. Если вы хотите начать использовать ссылочные типы, потому что «он стал ближе к Java, чтобы быть действительно объектно-ориентированным», то это ваш призыв, но, как вы обнаружите, у этого подхода есть недостатки. Другой проблемой будет производительность.

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

В итоге: если ссылочные типы вызывают у вас проблемы, не используйте их. Но не говорите «автобокс - это плохо» только потому, что они оказались бесполезными в вашей ситуации.

0
ответ дан 6 December 2019 в 05:42
поделиться

Я видел по крайней мере один случай, когда значение null было полезным. Многие объекты данных в веб-сервисах имеют логические поля, допускающие значение NULL. Иногда пользователь пренебрегает включением значения. В этом случае вы хотите отличить отсутствие значения от значения по умолчанию. Раньше люди писали методы getX , setX и isXSet () , где isXSet возвращает false, пока кто-то не вызовет setX . Теперь можно сделать X типом, допускающим значение NULL, и ясно, что он не был установлен, если getX возвращает null .

7
ответ дан 6 December 2019 в 05:42
поделиться

Думаю, это скорее философский, чем технический вопрос. Когда вы преобразуете примитивный тип в ссылочный тип, вы должны быть готовы к тому, что ссылочные типы (то есть объекты) допускают значение NULL.

Вы можете посмотреть презентацию The Billion Dollars Mistake , где C.A.R. Хоар говорит, что введение им нулевых ссылок на oop (Algol 60) было ошибкой.

Джош Блох из Effective Java рекомендует предпочитать примитивные типы там, где это возможно. Но иногда вам нужно проверить логическую переменную на значение null.

1
ответ дан 6 December 2019 в 05:42
поделиться

Это проблема автобоксинга, так же как Integer i = null;. Integer объект может быть null, в то время как родной int не может.

0
ответ дан 6 December 2019 в 05:42
поделиться

Ваша проблема связана с автонебоксированием, а не с автобоксированием. Я считаю автобоксинг злом по более существенным причинам:

Рассмотрим это:

Integer i = new Integer(1);
Integer i2 = new Integer(12);

System.out.println(i == 10 || i != i2);

Один == разбоксирует, а другой нет.

Унбоксинг для операторов (в отличие от присваиваний) был ошибкой, на мой взгляд (учитывая вышесказанное - это просто не Java). А вот боксирование - это очень хорошо.

4
ответ дан 6 December 2019 в 05:42
поделиться

На самом деле нет большой разницы по сравнению с днями до Java 1.5 - проблема не в логическом типе (у него все еще есть два состояния), а в логической оболочке (у которой всегда было 3 состояния. Boolean.TRUE, Boolean.FALSE и null ).

Каждое преобразование из логического объекта в логический примитив требует нулевых проверок с автобоксингом или без него.

0
ответ дан 6 December 2019 в 05:42
поделиться

Автобоксинг автоматически преобразует типы данных между внутренними типами и типами объектов.

Объектные типы для Boolean могут быть Boolean.TRUE, Boolean.FALSE, или null. Поэтому для булева значения необходимо иметь дело с 3 возможными значениями.

В базах данных часто бывает три состояния для типа boolean. Рассмотрим запись, которая отслеживает, сдал ли кто-то зачет по предмету. Есть TRUE, если он сдал, FALSE, если не сдал, и NULL, если "в настоящее время посещает занятия". Да, это странно, но отсутствие значения наследуется в объектно-ориентированном программировании.

Я тоже нахожу автобоксинг немного неприятным, в основном потому, что это функция, когда компилятор добавляет байткод для обработки процесса преобразования. На мой взгляд, это может привести к тому, что люди забывают о важных деталях в процессе преобразования, которые лучше было бы запомнить (например, обработка null в вашем случае). Это полезно, но не так полезно, как большинство других возможностей языка Java.

Лично мне хотелось бы, чтобы intrinsics были реализованы как легковесные объекты вместо "встроенных" типов. Очень часто гибридная система типов intrinsic / object мешает. С другой стороны, предполагалось, что intrinsics будут использоваться для повышения производительности, но похоже, что если вы должны делать много маршалинга от intrinsic к Object, вы не сможете насладиться приростом производительности только за счет intrinsic.

0
ответ дан 6 December 2019 в 05:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: