Должен ли я никогда больше не использовать примитивные типы? - PullRequest
16 голосов
/ 24 сентября 2008

Смешивание использования примитивных типов данных и их соответствующих классов-оболочек в Java может привести к множеству ошибок. Следующий пример иллюстрирует проблему:

int i = 4;
...
if (i == 10)
  doStuff();

Позже вы поймете, что хотите, чтобы переменная i была либо определена, либо неопределена, поэтому вы изменяете приведенную выше реализацию на:

Integer i = null;

Теперь проверка на равенство не пройдена.

Это хорошая практика Java всегда использовать примитивные классы-обертки? Это, очевидно, могло бы устранить некоторые ошибки на раннем этапе, но каковы недостатки этого? Влияет ли это на производительность или объем памяти приложения? Есть какие-нибудь подлые ошибки?

Ответы [ 8 ]

18 голосов
/ 24 сентября 2008

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

При выполнении сравнения (например, (i == 10)) java должен распаковать тип перед выполнением сравнения. Даже при использовании i.equals(TEN) используется вызов метода, который стоит дороже и (IMO) сложнее синтаксиса ==.

В памяти, объект должен храниться в куче (что также влияет на производительность), а также сохранять само значение.

Подлый готч? i.equals(j) когда я null.

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

8 голосов
/ 24 сентября 2008

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

Обычно, при использовании более новых версий Java, мне не нужно явно создавать или приводить к объектным версиям примитивов из-за поддержки авто-бокса, которая была добавлена ​​некоторое время в 1.5 (может быть, сама 1.5).

3 голосов
/ 24 сентября 2008

Я бы рекомендовал использовать примитивы все время, если у вас нет понятия «ноль».

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

Для чисел с плавающей запятой / двойников вы можете рассматривать NaN как ноль, но помните, что NaN! = NaN, поэтому вам все еще нужны специальные проверки, такие как! Float.isNaN (x).

Было бы очень хорошо, если бы были коллекции, которые поддерживали примитивные типы, вместо того, чтобы тратить время / накладные расходы на бокс.

1 голос
/ 24 сентября 2008

В вашем примере оператор if будет в порядке, пока вы не превысите 127 (поскольку целочисленная автобокс будет кэшировать значения до 127 и возвращать один и тот же экземпляр для каждого числа до этого значения)

Так что это хуже, чем ты это представляешь ...

if( i == 10 )

будет работать как раньше, но

if( i == 128 )

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

0 голосов
/ 25 сентября 2008

Когда вы добрались до этого пункта «Позже», во время рефакторинга нужно было выполнить немного больше работы. Используйте примитивы, когда это возможно. (Период капитала) Затем сделайте POJO, если требуется больше функциональности. На мой взгляд, примитивные классы-обертки лучше всего использовать для данных, которые должны передаваться по проводам, то есть для сетевых приложений. Принятие значений NULL в качестве допустимых значений вызывает головные боли по мере «роста» системы. Большая часть кода теряется или пропускается, защищая то, что должно быть простым сравнением.

0 голосов
/ 24 сентября 2008

Не переключайтесь на не примитивы только для того, чтобы получить эту возможность. Используйте логическое значение, чтобы указать, было ли установлено значение или нет. Если вам не нравится это решение, и вы знаете, что ваши целые числа будут в некотором разумном пределе (или не заботитесь о случайном сбое), используйте конкретное значение для обозначения «неинициализированный», например Integer.MIN_VALUE. Но это гораздо менее безопасное решение, чем логическое.

0 голосов
/ 24 сентября 2008

Если это значение может быть пустым, вы можете обнаружить, что в вашем дизайне вам нужно что-то еще.

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

Если это просто данные для отображения / хранения, вы можете подумать об использовании реального DTO - такого, у которого его вообще нет в качестве первоклассного члена. У них обычно есть способ проверить, установлено ли значение или нет.

Если в какой-то момент вы проверяете ноль, возможно, вы захотите использовать подкласс, потому что, когда есть одно различие, обычно их больше. По крайней мере, вам нужен лучший способ обозначить вашу разницу, чем «if primitiveIntValue == null», который на самом деле ничего не значит.

0 голосов
/ 24 сентября 2008

У тебя есть java POD-типы. Помимо накладных расходов, вы не можете выполнять обычные операции с объектами. Целое число - это объект, который необходимо выделить и собрать мусор. Инт не.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...