Пул integer в java

Что такое классы-обертки?

Значение примитива становится объектом, чтобы выполнять различные операции ( .parseInt()).

Примитивы не имеют методов.

Объекты классов-оберток являются неизменяемыми (Immutable).

Что такое автоупаковка и автораспаковка?

Для присваивания ссылок-примитивов объектам их классов-оберток (и наоборот) не требуется ничего делать, все происходит автоматически

Автоупаковка и распаковка не работают для массивов.

Автоупаковка — это механизм неявной инициализации объектов классов-оберток (Byte, Short, Integer, Long, Float, Double, Character, Boolean) значениями соответствующих им исходных примитивных типов (byte, short, int. ), без явного использования конструктора класса.

Автоупаковка происходит при прямом присваивании примитива классу-обертке (с помощью оператора =), либо при передаче примитива в параметры метода (типа класса-обертки).

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

Автоупаковка переменных примитивных типов требует точного соответствия типа исходного примитива типу класса-обертки.

Например, попытка упаковать переменную типа byte в Short, без предварительного явного приведения byte в short вызовет ошибку компиляции.

Автоупаковка констант примитивных типов допускает более широкие границы соответствия.

В этом случае компилятор способен предварительно осуществлять неявное расширение/сужение типа примитивов.

Неявное расширение/сужение исходного типа примитива до типа примитива соответствующего классу-обертке (для преобразования int в Byte, сначала компилятор самостоятельно неявно сужает int к byte) автоупаковку примитива в соответствующий класс-обертку.

Однако, в этом случае существуют два дополнительных ограничения:

a) присвоение примитива обертке может производится только оператором = (нельзя передать такой примитив в параметры метода без явного приведения типов)

b) тип левого операнда не должен быть старше чем Character, тип правого не должен старше, чем int.

Допустимо расширение/сужение byte в/из short, byte в/из char, short в/из char и только сужение byte из int, short из int, char из int. Все остальные варианты требуют явного приведения типов.

Дополнительной особенностью целочисленных классов-оберток созданных автоупаковкой констант в диапазоне -128 . +127 является то, что они кэшируются JVM. Поэтому такие обертки с одинаковыми значениями будут являться ссылками на один объект.

Приведение типов

Что такое явное и неявное приведение типов?
В каких случаях в JAVA нужно использовать явное приведение?

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

Неявные – выполняются автоматически (расширяющие преобразования, сужающие с потерей данных: int->float, long->float, long->double).

Явные – надо указывать тип (сужающие преобразования от типа с большей разрядностью к типу с меньшей разрядностью). Потеря данных (старшие биты будут потеряны).

Схема приведения типов

↓ИЗ | В→ boolean byte short char int long float double
boolean N N N N N N N
byte N Y C Y Y Y Y
short N C C Y Y Y Y
char N C C Y Y Y Y
int N C C C Y Y* Y
long N C C C C Y* Y*
float N C C C C C Y
double N C C C C C C

C — сужающее преобразование, требующее явного приведения

Y* — автоматическое расширяющее преобразование, в процессе которого значение может потерять некоторые из наименее значимых разрядов

Разновидности приведения:

  • Тождественное (identity) — Преобразование выражения любого типа к точно такому же типу всегда допустимо и происходит автоматически.
  • Расширение (повышение, upcasting) примитивного типа (widening primitive) — Означает, что осуществляется переход от менее емкого типа к более ёмкому. Этот тип приведения всегда допустим и происходит автоматически. Например, от типа byte (длина 8 бит) к типу int (длина 32 бита). Такие преобразование безопасны в том смысле, что новый тип всегда гарантировано вмещает в себя все данные, которые хранились в старом типе и таким образом не происходит потери данных.
  • Сужение (понижение, downcasting) примитивного типа (narrowing primitive) — Означает, что переход осуществляется от более емкого типа к менее емкому. При таком преобразовании есть риск потерять данные . В Java такое преобразование должно совершаться явным образом, при этом все старшие биты, не умещающиеся в новом типе, просто отбрасываются — никакого округления или других действий для получения более корректного результата не производится. Например, если число типа int было больше 127, то при приведении его к byte значения битов старше восьмого будут потеряны.
  • Расширение объектного типа (widening reference) — Означает неявное восходящее приведение типов или переход от более конкретного типа к менее конкретному, т.е. переход от потомка к предку. Разрешено всегда и происходит автоматически.
  • Сужение объектного типа (narrowing reference) — Означает нисходящее приведение, то есть приведение от предка к потомку (подтипу). Возможно только если исходная переменная является подтипом приводимого типа. Требует явного указания типа. При несоответствии типов в момент выполнения выбрасывается исключение ClassCastException.
  • Преобразование к строке (to String) — Любой тип может быть приведен к строке, т.е. к экземпляру класса String.
  • Запрещенные преобразования (forbidden) — Не все приведения между произвольными типами допустимы. Например, к запрещенным преобразованиям относятся приведения от любого ссылочного типа к примитивному и наоборот (кроме преобразования к строке). Кроме того невозможно привести друг к другу классы находящиеся на разных ветвях дерева наследования и т.п.

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

Для проверки возможности приведения нужно воспользоваться оператором instanceof :

if (parent instanceof Child)

Child child = (Child) parent;

Что такое пул интов?

Для более эффективного использования памяти, в JAVA используются так называемые пулы.

Есть строковый пул, Integer pool и тд. Когда мы создаем объект не используя операцию new, объект помещается в пул, и в последствии, если мы захотим создать такой же объект (опять не используя new), новый объект создан не будет, а мы просто получим ссылку на наш объект из пула.

Особенность Integer-пула — он хранит только числа, которые помещаются в тип данных byte: от -128 до 127. Для остальных чисел пул не работает.

Какие нюансы у строк в Java?

Это неизменяемый (immutable) (не меняется после создания) и финализированный (без потомков) тип данных; потокобезопасный может использоваться в многопоточке

  • Все объекты класса String JVM хранит в пуле строк;
  • Объект класса String можно получить используя двойные кавычки;
  • Можно использовать оператор + для конкатенации строк;
  • Начиная с Java 7 строки можно использовать в конструкции switch.

Каждый объект можно привести к строке .toString

Что такое пул строк?

Пул строк – это набор строк хранящийся в Heap .

Пул строк возможен благодаря неизменяемости строк в Java и реализации идеи интернирования строк;

Интернирование строк — это механизм, при котором одинаковые литералы представляют собой один объект в памяти.

Пул строк помогает экономить память, но по этой же причине создание строки занимает больше времени;

Когда для создания строки используются » , то сначала ищется строка в пуле с таким же значением, если находится, то просто возвращается ссылка, иначе создается новая строка в пуле, а затем возвращается ссылка на неё;

При использовании оператора new создается новый объект String. Затем при помощи метода intern() эту строку можно поместить в пул или же получить из пула ссылку на другой объект String с таким же значением;

System.out.println(«q==w: » + (q==w)); //true

System.out.println(«q==r: » + (q==r)); //false

System.out.println(«q==t: » + (q==t)); //true

Пул строк является примером паттерна «Приспособленец» (Flyweight).

Почему String неизменяемый и финализированный класс?

  • Пул строк возможен только потому, что строка неизменяемая, таким образом виртуальная машина сохраняет больше свободного места в Heap, поскольку разные строковые переменные указывают на одну и ту же переменную в пуле. Если бы строка была изменяемой, то интернирование строк не было бы возможным, потому что изменение значения одной переменной отразилось бы также и на остальных переменных, ссылающихся на эту строку.
  • Если строка будет изменяемой, тогда это станет серьезной угрозой безопасности приложения. Например, имя пользователя базы данных и пароль передаются строкой для получения соединения с базой данных и в программировании сокетов реквизиты хоста и порта передаются строкой. Так как строка неизменяемая, её значение не может быть изменено, в противном случае злоумышленник может изменить значение ссылки и вызвать проблемы в безопасности приложения.
  • Неизменяемость позволяет избежать синхронизации: строки безопасны для многопоточности и один экземпляр строки может быть совместно использован различными потоками.
  • Строки используются classloader-ом и неизменность обеспечивает правильность загрузки класса.
  • Поскольку строка неизменяемая, её hashCode() кэшируется в момент создания и нет необходимости рассчитывать его снова. Это делает строку отличным кандидатом для ключа в HashMap т.к. его обработка происходит быстрее.

Какая основная разница между String, StringBuffer, StringBuilder?

Класс String String является неизменяемым ( immutable ) — модифицировать объект такого класса нельзя, можно лишь заменить его созданием нового экземпляра.

Класс StringBuffer изменяемый — использовать StringBuffer следует тогда, когда необходимо часто модифицировать содержимое. Потокобезопасный . Синхронизирован ные методы работают медленнее не сихнронизированных.

Класс StringBuilder был добавлен в Java 5 и он во всем идентичен классу StringBuffer за исключением того, что он не синхронизирован и поэтому его методы выполняются значительно быстрей .

Класс StringJoiner используется, чтобы создать последовательность строк, разделенных разделителем с возможностью присоединить к полученной строке префикс и суффикс:

StringJoiner joiner = new StringJoiner(«.», «prefix-«, «-suffix»);

for (String s : «Hello the brave world».split(» «))

Что такое сигнатура метода?

Объявление метода — это весь код, который описывает метод.

модификатор_доступа + тип_возвращаемого_значения + имя_метода(список_параметров) + исключения

Сигнатура — название метода и типы параметров в определенном порядке. methodName(double, int)

Контракт метода — сигнатура метода, в сочетании с типом возвращаемого значения. В контракт также входят типы возбуждаемых методом исключений.

Насколько я понял модификатор доступа ни куда не входит.

Каким образом переменные передаются в методы, по значению или по ссылке?

Java передает параметры по значению. Всегда.

Скопировать значение внутри х и записать эту копию в у.

Ссылка А копируется в ссылку B. К объекту это не относится — у нас по-прежнему всего один объект. Но теперь есть две различных ссылки, контролирующие один и тот же объект Cat.

Источник

Кеширование или Integer пул?

Как работает кеширование при операции autoboxing? Начиная с Java 1.5, для целочисленных значений в диапазоне от -128 до + 127 объекты-обёртки кешируются внутри для повторного использования. В классе-обёртке Integer есть внутренний класс IntegerCache. Он объявлен как private static. В этом внутреннем классе кешированные объекты находятся в массиве cache[]. Кеширование выполняется при первом использовании класса-обёртки. После первого использования, вместо создания нового экземпляра (кроме использования конструктора), используются кешированные объекты. Код метода valueOf() класса Integer выгдядит так: Кэширование касается не только класса-оболочки Integer. Имеются аналогичные реализации кеширования для других классов-оболочек целочисленных типов: ByteCache, ShortCache, LongCache, CharacterCache. Кешированные объекты не используются при создании объекта-обёртки с помощью конструктора. На хабре есть статья, в которой SSiarhei (предполагаю, что крутой программист, потому что сдавал экзамен Oracle Certified Professional Java Programmer), в 2011 году написал: https://habr.com/ru/post/111189/ Так что происходит на самом деле? Есть ли Integer пул, и если да, то какую роль он играет?

Источник

Читайте также:  Kotlin serialization ignore field
Оцените статью