Почему автобокс в Java позволяет мне иметь 3 возможных значения для логического значения? - PullRequest
7 голосов
/ 27 мая 2010

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

"Если ваша программа попытается автоматически отключить null, она выдаст исключение NullPointerException."

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

но давайте подумаем о том факте, что вы получите NPE при попытке автоматической установки нуля.это означает, что вы не можете безопасно выполнять логические операции над логическими параметрами без проверки на ноль или обработки исключений.То же самое относится и к математическим операциям над Integer.

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

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

Ответы [ 9 ]

16 голосов
/ 27 мая 2010

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

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

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

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

7 голосов
/ 27 мая 2010

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

5 голосов
/ 27 мая 2010

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

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

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

4 голосов
/ 27 мая 2010

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

Учтите это:

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

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

Один == распаковывает, а другой нет.

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

1 голос
/ 27 мая 2010

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

Вы можете посмотреть Ошибка миллиарда долларов презентацию, где С.А.Р. Хоар говорит, что его введение нулевых ссылок на oop (Алгол 60) было ошибкой.

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

0 голосов
/ 27 мая 2010

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

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

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

0 голосов
/ 27 мая 2010

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

0 голосов
/ 27 мая 2010

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

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

0 голосов
/ 27 мая 2010

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

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

В базах данных обычно существует три состояния для логического типа. Рассмотрим запись, которая отслеживает, прошел ли кто-то класс. Есть ИСТИНА, для прохождения; ЛОЖЬ для не прохождения, и НЕДЕЙСТВИТЕЛЬНЫЙ для «в настоящее время взятие класса». Да, это странно, но отсутствие значения наследуется в объектно-ориентированном программировании.

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

Лично мне бы хотелось, чтобы встроенные функции были реализованы в виде легких объектов, а не "встроенных" типов. Во многих случаях мешает гибридная система внутренних / объектных типов. Тем не менее, встроенные функции должны были существовать для повышения производительности, но, похоже, что если вам необходимо многое сделать для маршаллинга объектов, вы не сможете насладиться повышением производительности только благодаря встроенным функциям.

...