ТЛ; др
есть ли накладные расходы памяти?
- Да, объекты занимают больше памяти, чем примитивы.
- Автобокс имеет небольшую стоимость как памяти, так и производительности.
Что происходит внутри класса Number, когда я назначаю ему эти 3 типа данных?
Ничего особенного не происходит, когда вы назначаете объект Integer
, Long
или Double
для List<Number>
.
Но что-то особенное происходит , когда вы назначаете примитив объекту его класса-обертки: автоматическая упаковка примитивов в объекты. Это происходит в первых трех строках, где вы заполняете объект Double
, Integer
и Long
, присваивая примитивное значение.
Если ваша среда настолько сильно ограничена (ограничена в памяти), вы должны не использовать любое из названий классов начальной заглавной буквы: Byte
, Short
, Integer
, Long
, Float
, Double
, Number
. Используйте примитивные массивы с примитивными типами. Но делайте используйте типы (обсуждаемые ниже) вместо того, чтобы придумывать свое побитовое побитовое управление, если у вас нет явной доказанной причины.
можно ли поставить Double там и не ожидать потери точности, когда я попытаюсь вернуть его как Double?
Нет преобразования, когда объект Double
удерживается как Number
. Double
объект уже Number
по наследованию . Каждый Double
объект Number
, но не каждый Number
Double
.
Подробнее
Number
- это абстрактный класс (см. Tutorial ), означающий, что он не предназначен для непосредственного создания экземпляра. Он рассчитан на подкласса , и эти подклассы, в свою очередь, могут быть созданы.
Вам нужно узнать разницу между типами примитивов и типами объектов . Java предлагает оба типа систем . Примитивные значения (см. Tutorial ) не объектно-ориентированы. Примитивы были разработаны для Java, чтобы облегчить (а) программистам, не разбирающимся в ООП, изучение нового языка Java, и (б) портирование кода из других языков, которые имеют схожую систему типов (, например C ). Кроме того, у примитивов есть преимущества, заключающиеся в том, что они занимают мало памяти и работают быстро. Объекты, напротив, занимают больше памяти и не так быстры для выполнения, но гораздо более гибкие и сложные.
Некоторые люди утверждают, что вы можете спроектировать язык программирования так, чтобы он обладал лучшим из обоих, предоставляя только типы объектов, поддерживая при этом некоторые из них примитивными типами ... но это не , что делает Java (в настоящее время) так что здесь мы отложим эту тему в сторону.
Java смешивает типы примитивов и объектов в одном и том же коде. Есть даже эквивалентные типы объектов для каждого из числовых примитивов. Обратите внимание на соглашения о буквенном регистре, где строчные буквы указывают тип примитива, а начальные прописные буквы указывают тип объекта. Каждый из перечисленных ниже классов начальной капитализации является подклассом Number
.
- Для примитива
byte
у нас есть класс Byte
, оба 8-бит (октет) держатели целых чисел со знаком, в диапазоне от -128 до 127 (включительно).
- Для примитива
short
у нас есть класс Short
, оба 16-битные держатели целых чисел со знаком, в диапазоне от -32 768 до 32 767 (включительно) .
- Для примитива
int
у нас есть класс Integer
, оба 32-битные держатели целых чисел со знаком, с диапазоном -2 31 до максимального значения 2 31 -1 (примерно ± 2 млрд.).
- Для примитива
long
у нас есть класс Long
, оба держателя 64-битных целых чисел со знаком, с диапазоном -2 63 и максимальным значением 2 63 -1.
- Для примитива
float
у нас есть класс Float
, оба 32-битных знака с плавающей запятой числа.
- Для примитива
double
у нас есть класс Double
, оба 64-битных знака с плавающей запятой числа.
Почему мы беспокоимся о классах-обёртках, если у нас уже есть примитивы? Для совместимости с другим кодом, который ожидает объекты. Самый большой пример - Java Collections Framework .
Последние поколения Java добавили auto-boxing , чтобы преодолеть разрыв между системами типов путем генерации кода преобразования во время компиляции. Автобокс преобразует примитивные типы данных в их соответствующий класс-оболочку.
Автобокс был добавлен, чтобы упростить жизнь программистам, но для компьютера это больше работы во время выполнения. Бокс означает поиск соответствующего класса, создание экземпляра объекта этого класса и присвоение значения примитива этому объекту. Распаковка означает обратное, значение должно быть извлечено из объекта и помещено в память, где живет примитив.
Во многих приложениях эти накладные расходы, добавляемые при распаковке и распаковке, незначительны для общей производительности приложения. Но в более экстремальных случаях, когда большое количество чисел обрабатывается часто, программист может решить избежать упаковки, избежать объектов и использовать только примитивы.
Double someDouble = 0.24;
Integer someInteger = 234;
Long someLong = 253263632L;
В каждой из трех строк выше у вас есть примитивное значение справа, которое автоматически помещается в объект слева. Функция автобоксирования в Java делает этот вид почти незаметным, потому что в обычных компьютерных средах мы, как правило, не заботимся о снижении производительности и памяти, связанных с автобоксом. Но если вы программируете для ограниченных сред, вы можете избегать объектов Number
и List
. Но затем вы отказываетесь от удобства полиморфизма (рассматривая Double
& Integer
& Long
все как Number
).
Аналогично, я предполагаю, что ваш метод doSomeMathOnNumber(n)
выполняет некоторую распаковку, переходя от объектов обратно к примитивам. Больше памяти и циклов ЦП.
(для лучшей производительности) Я использую байтовый массив и ByteBuffer и помещаю свои измерения с разными типами,
Хотя я не эксперт в программировании в стесненных условиях, я думаю, вы слишком усердно работаете. Я подозреваю, что простые массивы Java, содержащие типы byte
, short
и т. Д., Будут соответствовать вашим потребностям.
Для получения дополнительной информации, поиск переполнения стека для вопроса, такого как этот, Почему мы используем автобокс и распаковку в Java? .
Между прочим, типы с плавающей запятой уступают точности для скорости выполнения. Они не подходят для вопросов, где важна точность, таких как отслеживание денег. Для таких целей используйте класс BigDecimal
, медленный, но точный.