14

Про примитивы в Java, их жирненькие обертки и не только

Про примитивы в Java, их жирненькие обертки и не только Telegram (ссылка), IT, Программист, Java, Длиннопост

Вроде и маленькие, но жирненькие.

Примитивы и их обертки вроде как очевидны.

Примитивы и обертки являются базовыми элементами в Java. Тем не менее многие, даже опытные специалисты, имеют пробелы в этой теме. В этой статье мы рассмотрим самые важные аспекты примитивов и их оберток.

Примитивы в Java включают в себя 8 типов, из которых 6 относятся к численным.

Целочисленные:

  1. BYTE: тип с диапазоном от -128 до 127

  2. SHORT: тип с диапазоном -32768 до 32767

  3. INT: один из самых популярных типов, диапазон от -2^31 до 2^31-1

  4. LONG: тип с диапазоном значений от -2^63 до 2^63-1

Числа с плавающей точкой.

Куда хитрее стоит дело с числами с плавающей точкой. Тут пользователю дают 32 бита (float) или 64 бита (double), и он может тратить их на целую часть или на часть после плавающей точки. Оценить масштабность этих числе мы можем следующим образом:

Минималный "шаг" между двумя такими числами будет авен:

  • Float.MIN_VALUE ~ 1.40239846e-45

  • Double.MIN_VALUE ~ 4.9e-324

Максимальное число, если после запятой не будет дробных частей (те мы словно станем целочисленной переменной):

  • Float.MAX_VALUE ~ 3.4e+38

  • Double.MAX_VALUE ~ 1.79e+308

Резюмируя: чем более точно наше число (то есть, чем больше чисел после плавающей точки), тем меньше его абсолютное значение. Поскольку числа "до" запятой, то есть целочисленная часть, уменьшаются, увеличивается точность представления дробной части.

Булевы и Символные примитивы.

Ну и на последок - логические и символьные типы:

  • boolean - имеет значение true/false

  • char - символьный примитив может представлять максимум 65536 символов.

Что нужно знать о примитивах?

Основные характеристики примитивов:

  • Быстры в работе

  • Легковестны

Переполнение нам не друг. В крайнем случае, мы спасаемся через BigInteger/BigDecimal.

Про примитивы в Java, их жирненькие обертки и не только Telegram (ссылка), IT, Программист, Java, Длиннопост

Когда переоценил длину примитива

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

  • Если умножить два Short, каждый из которых равен 200, то мы выйдем за границу 32768, и вместо 40000 мы получим -25536.

  • Если мы умножим два Integer (которые могут покрывать 2 миллиарда), каждый из которых равен 50000, то мы получим -1794967296 вместо 2.5 миллиарда.

Вывод - заранее подумай о границах значений. Если данные не влазят ни в один из типов то BigDecimal или BigInteger придут на помощь.

Обертки примитивов. Вроде и жирненькие но необходимые.

Для каждого примитива в Java существует его обертка. Например:

  • int обернут в Integer

  • double в Double

  • и так далее для каждого из 8 типов

Основная необходимость наличия оберток - использование их в коллекциях. Коллекции в Java, по дизайну, работают только с объектами. Такой код даже не скомпилируется:

Про примитивы в Java, их жирненькие обертки и не только Telegram (ссылка), IT, Программист, Java, Длиннопост

Так, к сожалению, делать нельзя.

Что дает класс обертка? Посмотрим на примере Integer

Классы-обертки в Java, такие как Integer, предоставляют ряд преимуществ и дополнительных функциональностей:

  1. Конвертация типов: Методы, такие как Integer.valueOf(), предоставляют возможность конвертировать значения одного типа в другой.

  2. Autoboxing/Unboxing: Обертки поддерживают автоматическую упаковку (autoboxing) и распаковку (unboxing) значений, обеспечивая плавную конвертацию между примитивами и объектами.

  3. Реализация equals/hashcode: Классы-обертки переопределяют методы equals() и hashCode(), что позволяет использовать их в качестве ключей в коллекциях, таких как HashMap, где хранение и поиск элементов основаны на хэш-функции.

  4. Имплементация Comparable: Классы-обертки реализуют интерфейс Comparable, что делает их подходящими для использования в упорядоченных коллекциях, таких как TreeMap.

  5. Дополнительные методы: Классы-обертки предоставляют различные вспомогательные методы, такие как min(), max(), bitCount() и другие.

И так один из самых важных моментов - обертки работают из коробки для коллекций. Но есть ли минусы у них?

Недостатки оберток. Жирнота, медлительность.

Обертки инкапсулируют в себя примитивы это мы уже знаем. И как следствие мы:

  • Тратим память на саму обертку, а учитывая минимальный размер слова в 64-битных операционных системах (32-битные не берем в расчет, они уходят в прошлое) - обертка просто непростительно разрастается.

  • Время на доступ к примитиву возрастает, так как добавляется лишний прыжок по ссылке обертки.

  • Время на autoboxing/unboxing

Давайте оценим размер примитива и размер обертки для 64х битных систем:

Про примитивы в Java, их жирненькие обертки и не только Telegram (ссылка), IT, Программист, Java, Длиннопост

Потеря минимум 3 раза.

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

Что делать, если размер памяти критичен?

Однако, если вы храните большие объемы числовых данных и эффективное использование памяти критично, у вас есть два варианта:

  • Вернуться к использованию старых добрых массивов, которые поддерживают примитивы.

  • Использовать библиотеки вроде FastUtil или Trove , которые предоставляют специализированные коллекции для работы с примитивами и оптимизированы для минимизации потребления памяти.

Производительность.

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

Надеюсь вам понравился разбор. Больше материалов по джаве и смежным технологиям вы можете найти в моем канале. Спасибо за внимание.