Когда следует использовать примитивы вместо объектов-оболочек?

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


person yanchenko    schedule 27.10.2008    source источник


Ответы (5)


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

На самом деле это реализация легковесный шаблон дизайна. Когда для общеизвестного значения происходит упаковка, вместо создания нового экземпляра оболочки предварительно созданный экземпляр извлекается из пула и возвращается.

Одно из следствий: по-прежнему не рекомендуется использовать автоупаковку для научных расчетов. Например, код d = a * b + c использует классы Integer для a, b, c и d, а сгенерированный код имеет вид d.valueOf(a.intValue() * b.intValue() + c.intValue( )). У всех этих вызовов методов есть свои накладные расходы, поэтому обычно рекомендуется использовать автоупаковку, когда это необходимо для хранения примитивов в коллекциях.

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


Jb добавляет важный комментарий:

Также Wrapper.valueOf(primitive) использует пул оберток. Так что предпочитайте Integer.valueOf(5) новому Integer(5)

person VonC    schedule 27.10.2008
comment
автобокс все же не рекомендуется использовать для научных расчетов? Да, это проблема только с производительностью, не так ли? - person grep; 08.03.2015
comment
@grep не уверен: я написал это более 6 лет назад. - person VonC; 08.03.2015

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

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

person Cheekysoft    schedule 27.10.2008

да, примитивы быстрее объектов. Начиная с Java 5 вы даже можете смешивать примитивы и объекты без ручного преобразования одного в другой. Об этом позаботится механизм автобокса.

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

person nkr1pt    schedule 27.10.2008
comment
В каких случаях они быстрее? передача ссылок выполняется так же быстро, как и передача примитивов. - person OJ.; 27.10.2008
comment
возьмем, например, int. Целое число — это объект, содержащий одно целое поле. Integer намного громоздче, чем int. Это похоже на коробку Fedex, содержащую int. - person nkr1pt; 27.10.2008

Если вам нужно хранить примитивы в коллекциях, вы можете использовать commons-primitives.

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

Однажды я работал над проектом, в котором для доступа к базе данных использовались примитивы (и доморощенный ORM):

 class Foo{
    int xxx = -1;
 ...
 }

И тогда у вас было:

 void persist(Foo foo){
     ...
     statement.setInt(15,foo.getXXX()==-1?null:foo.getXXX());
     ...
}

Боже это было зло.

person jb.    schedule 27.10.2008

Я бы сказал, что вам следует беспокоиться об использовании примитивов вместо оболочек только тогда, когда вы профилируете свое приложение и видите, что автоупаковка является проблемой производительности или памяти. По моему опыту, память становится проблемой до циклов ЦП, когда речь идет о примитивах и объектах-оболочках.

person carson    schedule 27.10.2008
comment
Я не согласен. Зачем ждать, пока производительность станет проблемой, когда можно написать эффективный код? В 9 случаях из 10 вам не нужны дополнительные функции, которые предлагает класс-оболочка, так зачем их использовать? - person alexmcchessers; 27.10.2008
comment
9 из 10 случаев, когда вам не нужно оптимизировать. В большинстве случаев вы получаете выгоду от функциональности автобокса, иначе зачем бы они ее добавили? Нет причин усложнять себе жизнь, если вы этого даже не заметите. - person carson; 27.10.2008
comment
Есть много возможностей языка Java, которые мне нужны лишь изредка. Это не значит, что они бесполезны или что их не следует добавлять. Автоупаковка — полезная функция в определенных обстоятельствах, но я считаю ненужным использовать обертки только ради того, чтобы они были. - person alexmcchessers; 27.10.2008
comment
Это просто вопрос сделать код более читабельным. Беспокойтесь о производительности, когда у вас есть проблема. - person carson; 27.10.2008
comment
В большинстве случаев примитивы более удобочитаемы. Я предпочитаю if(editable) вместо if(editable.booleanValue()) и if(foo‹0) вместо if(foo!=null && foo.intValue() ‹ 0). - person jb.; 27.10.2008
comment
jb, вернись и посмотри, что такое автобокс, потому что то, что ты говоришь, что тебе не нравится, тебе не нужно делать. - person carson; 27.10.2008
comment
Ты прав, извини. Синтаксически они равны. Но у меня был такой опыт в проектах pre 1.5, с которыми я работал в прошлом году. - person jb.; 27.10.2008
comment
По вашей логике, почему бы не хранить все в виде строки? Вы можете анализировать, когда вам нужно выполнить математику со значением. Затем перейдите к числовым типам данных, если профилирование показывает, что это узкое место. int/long/double есть в языке. Безумие не использовать их, за исключением случаев, таких как записи коллекции. - person John M; 27.10.2008
comment
Джон, ты упускаешь суть. Они нужны для того, чтобы сделать код лучше. С какой стати вы говорите о предварительной оптимизации кода? Нет абсолютно ничего плохого в использовании оберток. - person carson; 27.10.2008
comment
Я не считаю использование int вместо Integer предварительной оптимизацией. Именно так должен был быть написан этот производный от C язык. Я вижу Integer, Float и т. д. как обходные пути для случаев, когда вам нужен объект. Не первичные типы данных для числовых значений. - person John M; 17.11.2008
comment
Вы все еще упускаете суть. Если вы начинаете с Integer, а затем думаете, что вместо этого я должен использовать int для повышения производительности, значит, вы выполнили предварительную оптимизацию. Я ничего не сказал об их повсеместном использовании, я сказал не беспокоиться об этом, пока вы не докажете, что это проблема. - person carson; 19.11.2008