Почему в Java до сих пор используются примитивные типы?

Начиная с Java 5, у нас была упаковка / распаковка примитивных типов, так что int обернут в java.lang.Integer, и так далее, и тому подобное.

В последнее время я вижу много новых проектов Java (которые определенно требуют JRE как минимум версии 5, если не 6), которые используют int, а не java.lang.Integer, хотя последний гораздо удобнее использовать, поскольку у него есть несколько вспомогательных методов для преобразования в значения long и др.

Почему некоторые все еще используют в Java примитивные типы? Есть ли ощутимая выгода?


person Naftuli Kay    schedule 04.03.2011    source источник
comment
когда-нибудь задумывались о потреблении памяти и производительности?   -  person Tedil    schedule 05.03.2011
comment
@Tedil Хорошо, зачем им вообще вводить эту функцию, если, по вашему мнению, это, по сути, ловушка; воспринимаете лучшие функции за счет памяти и производительности? Я просто говорю.   -  person Naftuli Kay    schedule 05.03.2011
comment
@TK Потому что помещать примитивы в коллекции проблематично. В основном они ожидают, что разработчики будут знать о проблемах с производительностью при использовании функций.   -  person corsiKa    schedule 05.03.2011
comment
@TK: они ввели это, потому что иногда вам нужно или вы хотите использовать объекты-оболочки (в любое время, когда вы хотите сохранить значение в коллекции или передать его методу, требующему объект), и это делает работу намного удобнее .   -  person ColinD    schedule 05.03.2011
comment
@ glowcoder / ColinD Очень интересно. Я предполагаю, что мой следующий вопрос: почему в $ @ # $ они не оптимизировали JRE, чтобы по существу свести на нет это влияние на производительность, просто сделав классы-оболочки невидимыми и невесомыми? Я всегда думал об автобоксе как о чем-то, что действительно влияет на разработчиков только при написании кода, как об удобстве использования.   -  person Naftuli Kay    schedule 05.03.2011
comment
@TK Kocheran В основном потому, что new IntegeR(5) == new Integer(5) по правилам должен оцениваться как false.   -  person biziclop    schedule 05.03.2011
comment
@TK: Автобокс - это просто синтаксический сахар. Внизу объекты по-прежнему должны быть объектами, а примитивы должны быть примитивами. Есть определенные существенные различия в том, как эти функции работают, что, как я полагаю, не позволяет им делать обертки объектов чем-то невидимым и невесомым.   -  person ColinD    schedule 05.03.2011
comment
Почему бы им просто не разрешить перегрузку операторов ... Эта .equals() штука действительно заставляет меня хуже думать о Java.   -  person Oleh Prypin    schedule 05.03.2011
comment
См. GNU Trove или Mahout Collections или HPPC или ... для решений для коллекций примитивных типов. Те из нас, кто заботится о скорости, тратят время на использование большего примитивных типов, а не меньше.   -  person bmargulies    schedule 06.03.2011
comment
@corsiKa Когда вы используете оператор new, он всегда создает новый объект. Вы запросили новый объект, и вы получите новый объект.   -  person NullUserException    schedule 09.05.2014
comment
@OlehPrypin Преимущество запрета на перегрузку оператора состоит в том, что вы можете посмотреть на код Java и всегда будете знать, что он делает. На таком языке, как C ++, вы не знаете, какие операторы могли быть перегружены.   -  person NullUserException    schedule 09.05.2014
comment
@NullUserException Да, конечно. Это проиллюстрировано моим примером, в частности class biziclip, и моей поспешно сделанной правкой до истечения пятиминутного окна.   -  person corsiKa    schedule 09.05.2014
comment
Несвязно, но эта несогласованность в системе типов Java - одно из лучших улучшений, которые делает Scala.   -  person Paul Draper    schedule 01.06.2014


Ответы (21)


В статье Джошуа Блоха Эффективная Java , Правило 5: «Избегайте создания ненужных объектов», он публикует следующий пример кода:

public static void main(String[] args) {
    Long sum = 0L; // uses Long, not long
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    System.out.println(sum);
}

и запуск занимает 43 секунды. Включение Long в примитив сокращает его до 6,8 секунды ... Если это какое-то указание на то, почему мы используем примитивы.

Отсутствие равенства собственных значений также вызывает беспокойство (.equals() довольно многословен по сравнению с ==)

для бизиклопа:

class Biziclop {

    public static void main(String[] args) {
        System.out.println(new Integer(5) == new Integer(5));
        System.out.println(new Integer(500) == new Integer(500));

        System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
        System.out.println(Integer.valueOf(500) == Integer.valueOf(500));
    }
}

Результаты в:

false
false
true
false

EDIT Почему (3) возвращает true, а (4) возвращает false?

Потому что это два разных объекта. 256 целых чисел, ближайших к нулю [-128; 127] кэшируются JVM, поэтому они возвращают для них один и тот же объект. Однако за пределами этого диапазона они не кэшируются, поэтому создается новый объект. Чтобы усложнить ситуацию, JLS требует, чтобы было кэшировано по крайней мере 256 легковесов. Разработчики JVM могут добавить больше, если захотят, что означает, что это может работать в системе, где ближайшие 1024 кэшируются, и все они возвращают истину ... #awkward

person corsiKa    schedule 04.03.2011
comment
А теперь представьте, если бы i также был объявлен как Long! - person ColinD; 05.03.2011
comment
@ColinD: Я это тестировал. 32,6 секунды для выполнения приведенного выше кода и 59,9 секунды, если i также Long. Не совсем вдвое. Ой. - person Eddie; 05.03.2011
comment
Чтобы уточнить: к сожалению, не существует методов, позволяющих выполнять арифметические операции с Int, Long и т. д. - поэтому нет другого решения, кроме (un) бокса. Даже если бы они были, они бы просто использовали примитивные типы внутри. - person Dave O.; 05.03.2011
comment
В классе biziclop, не являются ли третье и четвертое утверждения ошибочно несовместимыми в своем результате? Прямо сейчас код говорит, что Integer.valueOf(5) == Integer.valueOf(5) разрешает true, но Integer.valueOf(500) == Integer.valueOf(500) разрешает false. - person John K; 05.03.2011
comment
@ Джон: Нет. Они правы. ;) Это может зависеть от конкретной JVM, но некоторые JVM оптимизируются, создавая легковесы для автоматически упакованных примитивных чисел, близких к нулю. - person TREE; 05.03.2011
comment
@ Джон, да, это безумие. К сожалению, поскольку люди часто проводят быстрые тесты с 1, 5 или другими небольшими значениями, они ошибочно полагают, что любое valueOf будет приравниваться к true. Я видел, как неопытные программисты приводили к более чем паре ошибок. - person corsiKa; 05.03.2011
comment
@TREE - спецификация на самом деле требует виртуальных машин для создания легковесов в определенном диапазоне. Но, к сожалению, это позволяет им расширять этот диапазон, а это означает, что программы могут вести себя по-разному на разных виртуальных машинах. Вот и все о кроссплатформенности ... - person Daniel Earwicker; 05.03.2011
comment
Java пошла насмарку, предлагая все больше и больше плохих вариантов дизайна. Автобоксинг - это полный провал, он ни надежен, ни предсказуем, ни портативен. Мне действительно очень интересно, о чем они думали ... вместо того, чтобы исправить ужасную двойственность примитивных объектов, им удалось сделать ее хуже, чем в первую очередь. - person Pop Catalin; 06.03.2011
comment
@Catalin Я не согласен с вами, что автобокс - полный провал. У него есть некоторые недостатки, которые ничем не отличаются от любого другого дизайна, который можно было бы использовать (включая ничего). Они очень ясно показывают, чего вы можете и чего не можете ожидать, и, как и любой другой дизайн, они ожидают, что разработчики будут знать и соблюдать контракты. этих дизайнов. - person corsiKa; 06.03.2011
comment
Я удивлен, что последние версии Hotspot не сократили разрыв между коробочным типом и примитивной производительностью. На моей машине примитивная версия приведенного выше кода в 11 раз быстрее. - person CromTheDestroyer; 13.04.2011
comment
Вы можете подумать, что оптимизировать довольно просто. Я не могу представить, что им мешает сделать это. - person corsiKa; 13.04.2011
comment
@NaftuliTzviKay Это не провал. Они делают его ОЧЕНЬ ЧИСТЫМ , что оператор == выполняет сравнения эталонных идентификаторов для Integer выражений и сравнения на равенство значений для int выражений. Integer.equals() существует именно по этой причине. Вы не должны никогда использовать == для сравнения значений в любом непримитивном типе. Это Java 101. - person NullUserException; 09.05.2014
comment
@NullUserException Я думаю, что Нафтули означает провал со стороны программиста, который делает что-то подобное (и держу пари, что такое случается часто!) - person corsiKa; 17.10.2014
comment
Проблема в том, что во всем виноват программист, и, очевидно, очень быстро понять проблему, если вы ее ищете, но если вы погружаетесь и выходите из нескольких разных языков, часто с разницей в месяцы или даже годы, каждый с разными соглашениями об именах и т. Д. ... очень легко сделать такую ​​ошибку и какое-то время не осознавать, что там вообще есть проблема. - person Chris Nevill; 19.10.2014
comment
Я считаю, что вопрос равноправия должен стоять на первом месте. Кроме того, упакованные типы подразумевают возможность быть null. Различия в производительности могут быть разрушительными, но все же семантические проблемы еще хуже. - person Holger; 26.05.2021

Автоунбоксинг может привести к трудно обнаруживаемым НПЭ

Integer in = null;
...
...
int i = in; // NPE at runtime

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

person Heiko Rupp    schedule 04.03.2011

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

person Brandon Frohbieter    schedule 04.03.2011

Примитивные типы:

int x = 1000;
int y = 1000;

Теперь оцените:

x == y

Это true. Вряд ли удивительно. Теперь попробуйте коробочные типы:

Integer x = 1000;
Integer y = 1000;

Теперь оцените:

x == y

Это false. Наверное. Зависит от времени выполнения. Достаточно ли этой причины?

person Daniel Earwicker    schedule 04.03.2011
comment
Причина: если мы используем классы Wrapper для создания переменной, она всегда будет создавать новую ссылку в памяти. - person Teja MS; 07.02.2021

Помимо проблем с производительностью и памятью, я хотел бы затронуть еще одну проблему: _ 1_ интерфейс будет нарушен без int.
Проблема заключается в перегруженном remove() методе (_ 4_ по сравнению с _ 5_). remove(Integer) всегда разрешает вызов последнего, поэтому вы не можете удалить элемент по индексу.

С другой стороны, при попытке добавить и удалить int есть ловушка:

final int i = 42;
final List<Integer> list = new ArrayList<Integer>();
list.add(i); // add(Object)
list.remove(i); // remove(int) - Ouch!
person xehpuk    schedule 18.07.2012
comment
Было бы сломано, да. Однако remove (int) - это недостаток дизайна IMO. Имена методов никогда не должны быть перегружены, если есть малейшая вероятность путаницы. - person MrBackend; 09.02.2015
comment
@MrBackend Достаточно справедливо. Интересно, что у Vector было removeElementAt(int) с самого начала. remove(int) был введен в среду коллекций в Java 1.2. - person xehpuk; 09.02.2015
comment
@MrBackend: когда был разработан List API, не существовало ни Generics, ни Autoboxing, поэтому не было шанса смешать remove(int) и remove(Object) - person Holger; 21.07.2015
comment
@Franklin Yu: конечно, но при разработке нового языка / версии без ограничений совместимости вы не остановитесь на изменении этой досадной перегрузки. Вы бы просто полностью избавились от различия примитивов и значений в рамке, так что вопрос о том, что использовать, никогда не появится. - person Holger; 09.05.2016

Вы действительно можете представить

  for (int i=0; i<10000; i++) {
      do something
  }

цикл с java.lang.Integer вместо этого? Java.lang.Integer является неизменяемым, поэтому каждое приращение цикла будет создавать новый объект java в куче, а не просто увеличивать int в стеке с помощью одной инструкции JVM. Спектакль был бы дьявольским.

Я действительно не согласен с тем, что гораздо удобнее использовать java.lang.Integer, чем int. Напротив. Autoboxing означает, что вы можете использовать int там, где в противном случае вы были бы вынуждены использовать Integer, а компилятор java позаботится о вставке кода для создания нового объекта Integer для вас. Autoboxing позволяет вам использовать int там, где ожидается Integer, а компилятор вставляет соответствующую конструкцию объекта. Это никоим образом не устраняет и не уменьшает потребность в int в первую очередь. С автобоксом вы получаете лучшее из обоих миров. Вы получаете целое число, созданное для вас автоматически, когда вам нужен java-объект на основе кучи, и вы получаете скорость и эффективность int, когда вы просто выполняете арифметические и локальные вычисления.

person Tom Quarendon    schedule 04.03.2011

Примитивные типы намного быстрее:

int i;
i++;

Целое число (все числа, а также строка) - это неизменяемый тип: однажды созданный, его нельзя изменить. Если i был целым числом, то i++ создал бы новый объект типа Integer - намного дороже с точки зрения памяти и процессора.

person Peter Knego    schedule 04.03.2011
comment
Вы не хотите, чтобы одна переменная изменялась, если вы делаете i++ для другой переменной, поэтому Integer вполне должен быть неизменяемым, чтобы иметь возможность делать это (или, по крайней мере, этот i++ должен был бы создать новый объект Integer в любом случае). (И примитивные значения также неизменны - вы просто не замечаете этого, поскольку они не являются объектами.) - person Paŭlo Ebermann; 05.03.2011
comment
@ Paŭlo: Утверждать, что примитивные значения неизменны, бессмысленно. Когда вы переназначаете примитивную переменную на новое значение, вы не создаете ничего нового. Распределение памяти не задействовано. Точка зрения Питера остается неизменной: i ++ для примитива не выделяет память, но для объекта это обязательно. - person Eddie; 05.03.2011
comment
@Eddie: (Он не обязательно требует выделения памяти, он также может возвращать кешированное значение. Думаю, для некоторых небольших значений это так.) Моя точка зрения заключалась в том, что неизменность целых чисел здесь не является решающим моментом, вы все равно захотите иметь другой объект, независимо от неизменности. - person Paŭlo Ebermann; 05.03.2011
comment
@ Palo: я хотел сказать только, что Integer на порядок медленнее примитивов. И это связано с тем, что упакованные типы неизменяемы, и каждый раз, когда вы меняете значение, создается новый объект. Я не утверждал, что с ними что-то не так или что они неизменяемы. Просто они медленнее и что кодировщик должен это знать. Посмотрите, как Groovy работает без примитивных типов jroller.com/rants/entry/why_is_groovy_so_slow - person Peter Knego; 05.03.2011
comment
Неизменяемость и ++ здесь отвлекающий маневр. Представьте, что Java была улучшена для поддержки перегрузки операторов очень простым способом, так что если класс (например, Integer имеет метод plus, тогда вы можете написать i + 1 вместо i.plus(1). И также предположим, что компилятор достаточно умен, чтобы развернуть i++ в i = i + 1. Теперь вы можете сказать i++ и эффективно увеличить переменную i, не изменяя Integer. - person Daniel Earwicker; 22.03.2011

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

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

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

person biziclop    schedule 04.03.2011
comment
Я не согласен. Аспект производительности может иметь решающее значение. Очень мало из этого, вероятно, связано с инерцией или силой привычки. - person Eddie; 05.03.2011
comment
@Eddie Может быть, но бывает очень редко. Поверьте мне, для большинства людей аргументы в пользу производительности - всего лишь отговорка. - person biziclop; 05.03.2011
comment
Я тоже хотел бы защитить аргумент о производительности. На Android с Dalvik каждый создаваемый вами объект увеличивает риск вызова GC, и чем больше у вас объектов, тем дольше будут паузы. Таким образом, создание целых чисел вместо int в цикле, вероятно, будет стоить вам нескольких пропущенных кадров. - person Igor Čordaš; 15.07.2014
comment
@PSIXO Это справедливый вопрос, я писал его исключительно для серверной Java. Мобильные устройства - совсем другое дело. Но я хотел сказать, что даже разработчики, которые в противном случае пишут ужасный код, не обращая внимания на производительность, будут ссылаться на это как на причину, с их точки зрения это звучит как оправдание. - person biziclop; 15.07.2014

Между прочим, в Smalltalk есть только объекты (без примитивов), и все же они оптимизировали свои маленькие целые числа (используя не все 32 бита, только 27 или что-то подобное), чтобы не выделять какое-либо пространство кучи, а просто использовать специальный битовый шаблон. Также другие общие объекты (true, false, null) имеют здесь специальные битовые шаблоны.

Итак, по крайней мере, на 64-битных JVM (с 64-битным пространством имен указателей) должна быть возможность вообще не иметь никаких объектов типа Integer, Character, Byte, Short, Boolean, Float (и small Long) (кроме созданных явным new ...()), только специальные битовые комбинации, с которыми можно довольно эффективно манипулировать обычными операторами.

person Paŭlo Ebermann    schedule 04.03.2011
comment
Я должен был сказать о некоторых реализациях, поскольку, я думаю, это не регулируется спецификациями языка. (И, к сожалению, я не могу здесь цитировать какие-либо источники, это только из того, что я где-то слышал.) - person Paŭlo Ebermann; 05.03.2011
comment
Итак, JIT уже хранит мета в указателе; В том числе указатель может хранить информацию GC или Klass (оптимизация Class - намного лучшая идея, чем оптимизация Integer, о которой мне наплевать). Для изменения указателя потребуется код shift / cmp / jnz (или что-то в этом роде) перед каждой загрузкой указателя. Ветвь, вероятно, не будет очень хорошо предсказана оборудованием (поскольку это может быть как тип значения, так и обычный объект), и это приведет к снижению производительности. - person bestsss; 11.03.2011
comment
Я занимался Smalltalk несколько лет. Оптимизация по-прежнему была довольно дорогой, так как для каждой операции с int приходилось демаскировать и повторно применять их. В настоящее время java находится на одном уровне с C при манипулировании примитивными числами. С демаскированием + маска, вероятно, будет на ›30% медленнее. - person R.Moeller; 05.06.2014

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

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

Другая причина заключалась в том, что (new Long (1000)) == (new Long (1000)) ложно, но это просто еще один способ сказать, что «.equals» не имеет синтаксической поддержки для упакованных типов (в отличие от операторов ‹,> , = и т.д.), поэтому мы возвращаемся к причине "более простого синтаксиса".

Я думаю, что пример непримитивного цикла Стива Йегге очень хорошо иллюстрирует мою точку зрения: http://sites.google.com/site/steveyegge2/language-trickery-and-ejb.

Подумайте об этом: как часто вы используете типы функций на языках, которые имеют для них хороший синтаксис (например, любой функциональный язык, python, ruby ​​и даже C) по сравнению с java, где вы должны моделировать их с помощью таких интерфейсов, как Runnable и Callable и безымянные классы.

person CromTheDestroyer    schedule 13.04.2011

Пара причин не избавляться от примитивов:

  • Обратная совместимость.

Если его исключить, никакие старые программы даже не запустятся.

  • Перезапись JVM.

Всю JVM пришлось бы переписать, чтобы поддерживать эту новую вещь.

  • Больший объем памяти.

Вам нужно будет сохранить значение и ссылку, которая использует больше памяти. Если у вас огромный массив байтов, использование byte значительно меньше, чем использование Byte.

  • Проблемы с нулевым указателем.

Объявление int i и выполнение чего-либо с i не вызовет проблем, но объявление Integer i и последующее выполнение того же результата приведет к NPE.

  • Вопросы равенства.

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

Integer i1 = 5;
Integer i2 = 5;

i1 == i2; // Currently would be false.

Было бы ложью. Операторы должны быть перегружены, и это приведет к серьезному переписыванию материала.

  • Медленный

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

person Anubian Noob    schedule 18.06.2014
comment
i1 == i2; будет ложным, только если i1 ›= 128. Итак, текущий пример неверен - person Geniy; 23.01.2019

Объекты намного тяжелее, чем примитивные типы, поэтому примитивные типы намного эффективнее, чем экземпляры классов-оболочек.

Примитивные типы очень просты: например, int имеет размер 32 бита, занимает ровно 32 бита в памяти и может управляться напрямую. Целочисленный объект - это законченный объект, который (как и любой объект) должен храниться в куче, и к нему можно получить доступ только через ссылку (указатель) на него. Скорее всего, он также занимает более 32 бит (4 байта) памяти.

Тем не менее, тот факт, что в Java есть различие между примитивными и непримитивными типами, также является признаком возраста языка программирования Java. В новых языках программирования такого различия нет; компилятор такого языка достаточно умен, чтобы самостоятельно определить, используете ли вы простые значения или более сложные объекты.

Например, в Scala нет примитивных типов; существует класс Int для целых чисел, а Int - это реальный объект (для которого вы можете использовать методы и т. д.). Когда компилятор компилирует ваш код, он за кулисами использует примитивные int, поэтому использование Int столь же эффективно, как использование примитивного int в Java.

person unk1102    schedule 04.03.2011
comment
Я бы предположил, что JRE будет достаточно умен, чтобы сделать это и с обернутыми в Java примитивами. Потерпеть поражение. - person Naftuli Kay; 05.03.2011

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

person Eddie    schedule 04.03.2011
comment
Извините, это не так. Интеллектуальная JVM может выполнять escape-анализ для любых выделений объектов и, если они не могут выйти, размещать их в стеке. - person rlibby; 05.03.2011
comment
Да, это начало быть особенностью современных JVM. Через пять лет то, что вы говорите, будет верным для большинства используемых в то время JVM. Сегодня это не так. Я почти что прокомментировал это, но решил не комментировать. Возможно, мне следовало что-то сказать. - person Eddie; 05.03.2011

У примитивных типов есть много преимуществ:

  • Более простой код для написания
  • Производительность лучше, поскольку вы не создаете экземпляр объекта для переменной.
  • Поскольку они не представляют собой ссылку на объект, нет необходимости проверять нули.
  • Используйте примитивные типы, если вам не нужно использовать преимущества бокса.
person Adriana    schedule 07.03.2014

Трудно понять, какие именно оптимизации происходят под прикрытием.

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

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

Кроме того, Integer имеет гораздо более высокие логические издержки по сравнению с int: теперь вам нужно беспокоиться о том, вызывает ли int a = b + c; исключение.

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

person Matthew Willis    schedule 04.03.2011

int loops = 100000000;

long start = System.currentTimeMillis();
for (Long l = new Long(0); l<loops;l++) {
    //System.out.println("Long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around Long: "+ (System.currentTimeMillis()- start));

start = System.currentTimeMillis();
for (long l = 0; l<loops;l++) {
    //System.out.println("long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around long: "+ (System.currentTimeMillis()- start));

Миллисекунды, затраченные на цикл 100000000 раз вокруг Long: 468

Миллисекунды, затраченные на цикл 100000000 раз вокруг long: 31

Кстати, я бы не прочь увидеть что-то подобное в Java.

Integer loop1 = new Integer(0);
for (loop1.lessThan(1000)) {
   ...
}

Где цикл for автоматически увеличивает loop1 от 0 до 1000 или

Integer loop1 = new Integer(1000);
for (loop1.greaterThan(0)) {
   ...
}

Где цикл for автоматически уменьшает loop1 1000 до 0.

person Keith    schedule 11.08.2014

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

Вы должны спросить, зачем нужен тип класса / объекта

Причина наличия типа объекта в том, чтобы облегчить нашу жизнь, когда мы имеем дело с коллекциями. Примитивы нельзя добавлять напрямую в список / карту, вам нужно написать класс-оболочку. Здесь вам помогут классы Readymade Integer, плюс у него есть много служебных методов, таких как Integer.pareseInt (str)

person Prabakaran    schedule 08.09.2015

Я согласен с предыдущими ответами, использование объектов-оберток примитивов может быть дорогостоящим. Но если производительность вашего приложения не критична, вы избегаете переполнения при использовании объектов. Например:

long bigNumber = Integer.MAX_VALUE + 2;

Значение bigNumber - -2147483647, и вы ожидаете, что это будет 2147483649. Это ошибка в коде, которую можно исправить, выполнив следующие действия:

long bigNumber = Integer.MAX_VALUE + 2l; // note that '2' is a long now (it is '2L').

И bigNumber будет 2147483649. Иногда такие ошибки легко пропустить и они могут привести к неизвестному поведению или уязвимостям (см. CWE-190).

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

Long bigNumber = Integer.MAX_VALUE + 2; // Not compiling

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

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

person Fernando Garcia    schedule 03.12.2016

Потому что JAVA выполняет все математические операции с примитивными типами. Рассмотрим этот пример:

public static int sumEven(List<Integer> li) {
    int sum = 0;
    for (Integer i: li)
        if (i % 2 == 0)
            sum += i;
        return sum;
}

Здесь операции напоминания и унарного плюса не могут применяться к типу Integer (Reference), компилятор выполняет распаковку и выполняет операции.

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

Как правило, лучше сохранять аргументы типа Ссылка и результат примитивного типа.

person user3462649    schedule 12.12.2014

Примитивные типы намного быстрее и требуют гораздо меньше памяти. Следовательно, мы можем предпочесть их использование.

С другой стороны, текущая спецификация языка Java не допускает использования примитивных типов в параметризованных типах (обобщенных типах), в коллекциях Java или API Reflection.

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

* Подробную информацию см. В источнике: https://www.baeldung.com/java-primitives-vs-objects

person Arun Joseph    schedule 12.06.2019

Чтобы быть кратким: примитивные типы быстрее и требуют меньше памяти, чем коробочные.

person White Link    schedule 12.06.2020