Бокс (информатика)
Эта статья нуждается в дополнительных цитатах для проверки . ( август 2009 г. ) |
В информатике ( упаковка также известная как упаковка) — это преобразование размещения примитивного типа внутри объекта так, чтобы значение можно было использовать в качестве ссылки . Распаковка — это обратное преобразование извлечения примитивного значения из объекта-оболочки. Автоупаковка — это термин, обозначающий автоматическое применение преобразований упаковки и/или распаковки по мере необходимости.
Бокс
[ редактировать ]Наиболее известное применение бокса приходится на Java , где существует различие между ссылочными типами и типами значений по таким причинам, как эффективность выполнения, а также синтаксические и семантические проблемы. На Яве LinkedList
может хранить только значения типа Object
. Возможно, кто-то пожелает иметь LinkedList
из int
, но это напрямую невозможно. Вместо этого Java определяет примитивные классы-оболочки, соответствующие каждому примитивному типу : Integer
и int
, Character
и char
, Float
и float
и т. д. Тогда можно определить LinkedList
используя коробочный тип Integer
и вставьте int
значения в список, указав их как Integer
объекты. (При использовании универсальных параметризованных типов, представленных в J2SE 5.0, этот тип представляется как LinkedList<Integer>
.)
С другой стороны, в C# нет примитивных классов-оболочек, но допускается упаковка значений любого типа, возвращая обобщенное значение. Object
ссылка. В Objective-C любое примитивное значение может иметь префикс @
сделать NSNumber
из этого (например @123
или @(123)
). Это позволяет добавлять их в любую из стандартных коллекций, например в NSArray
.
В Haskell практически нет понятия ссылочного типа , но он все еще использует термин «коробочный» для унифицированного представления объединения указателей на теги в системе времени выполнения . [1]
Упакованный объект всегда является копией объекта значения и обычно является неизменяемым . Распаковка объекта также возвращает копию сохраненного значения. Повторная упаковка и распаковка объектов может оказать серьезное влияние на производительность, поскольку упаковка динамически выделяет новые объекты, а распаковка (если упакованное значение больше не используется) делает их пригодными для сборки мусора . Однако современные сборщики мусора, такие как сборщик мусора Java HotSpot по умолчанию, могут более эффективно собирать недолговечные объекты, поэтому, если упакованные объекты недолговечны, влияние на производительность может быть не таким серьезным.
В некоторых языках существует прямая эквивалентность между неупакованным примитивным типом и ссылкой на неизменяемый упакованный тип объекта. Фактически, все примитивные типы в программе можно заменить коробочными типами объектов. В то время как присвоение одного примитива другому копирует его значение, присвоение одной ссылки на упакованный объект в другую копирует значение ссылки для ссылки на тот же объект, что и первая ссылка. Однако это не вызовет никаких проблем, поскольку объекты неизменяемы, поэтому семантически нет реальной разницы между двумя ссылками на один и тот же объект или на разные объекты (если только вы не посмотрите на физическое равенство). Для всех операций, кроме присваивания, таких как арифметические операции, сравнения и логические операторы, можно распаковать упакованный тип, выполнить операцию и повторно упаковать результат по мере необходимости. Таким образом, можно вообще не хранить примитивные типы.
Автобокс
[ редактировать ]Автоупаковка — это термин, обозначающий получение ссылочного типа из типа значения только посредством преобразования типа (неявного или явного). Компилятор автоматически предоставляет дополнительный исходный код, создающий объект.
Например, в версиях Java до J2SE 5.0 следующий код не компилировался:
Integer i = new Integer(9);
Integer i = 9; // error in versions prior to 5.0!
Компиляторы до версии 5.0 не принимали последнюю строку. Integer
являются эталонными объектами, на первый взгляд ничем не отличающимися от List
, Object
и так далее. Чтобы преобразовать из int
к Integer
, нужно было «вручную» создать экземпляр объекта Integer. Начиная с J2SE 5.0, компилятор принимает последнюю строку и автоматически преобразует ее так, что создается объект Integer для хранения значения. 9
. [2] Это означает, что начиная с J2SE 5.0 что-то вроде Integer c = a + b
, где a
и b
являются Integer
теперь скомпилируются — a и b распаковываются, целочисленные значения суммируются, а результат автоматически упаковывается в новый Integer
, который, наконец, сохраняется внутри переменной c
. Операторы равенства не могут использоваться таким образом, поскольку операторы равенства уже определены для ссылочных типов, для равенства ссылок; чтобы проверить равенство значений в коробочном типе, все равно необходимо вручную распаковать их и сравнить примитивы или использовать метод Objects.equals
метод.
Другой пример: J2SE 5.0 позволяет программисту обрабатывать коллекцию (например, LinkedList
), как если бы оно содержало int
ценности вместо Integer
объекты. Это не противоречит сказанному выше: коллекция по-прежнему содержит только ссылки на динамические объекты и не может перечислять примитивные типы. Это не может быть LinkedList<int>
, но это должно быть LinkedList<Integer>
вместо. Однако компилятор автоматически преобразует код так, что список будет «тихо» получать объекты, тогда как в исходном коде упоминаются только примитивные значения. Например, теперь программист может написать list.add(3)
и думать так, как будто int
3
были добавлены в список; но компилятор фактически преобразует строку в list.add(new Integer(3))
.
Автоматическая распаковка
[ редактировать ]При автоматической распаковке компилятор автоматически предоставляет дополнительный исходный код, который извлекает значение из этого объекта либо путем вызова какого-либо метода этого объекта, либо другими способами.
Например, в версиях Java до J2SE 5.0 следующий код не компилировался:
Integer k = new Integer(4);
int l = k.intValue(); // always okay
int m = k; // would have been an error, but okay now
C# не поддерживает автоматическую распаковку в том же смысле, что и Java, поскольку в нем нет отдельного набора примитивных типов и типов объектов. Все типы, которые в Java имеют как примитивную, так и объектную версию, автоматически реализуются компилятором C# либо как примитивные (значения), либо как объектные (ссылочные) типы.
В обоих языках автоматическое упаковывание не приводит к автоматическому понижению уровня, т. е. следующий код не будет компилироваться:
С#:
int i = 42;
object o = i; // box
int j = o; // unbox (error)
Console.WriteLine(j); // unreachable line, author might have expected output "42"
Ява:
int i = 42;
Object o = i; // box
int j = o; // unbox (error)
System.out.println(j); // unreachable line, author might have expected output "42"
Введите помощники
[ редактировать ]В современном Object Pascal есть еще один способ выполнения операций над простыми типами, близкий к упаковке, который называется помощниками типов во FreePascal или помощниками записи в Delphi и FreePascal в режиме Delphi.
Упомянутые диалекты представляют собой языки, компилируемые в собственный язык Object Pascal, и поэтому в них отсутствуют некоторые возможности, которые могут реализовать C# и Java. во время выполнения В частности, выведение типа для строго типизированных переменных.
Но особенность связана с боксом.
Это позволяет программисту использовать такие конструкции, как
{$ifdef fpc}{$mode delphi}{$endif}
uses sysutils; // this unit contains wraps for the simple types
var
x:integer=100;
s:string;
begin
s:= x.ToString;
writeln(s);
end.
Ссылки
[ редактировать ]- ^ «7.2. Распакованные типы и примитивные операции» . downloads.haskell.org . Проверено 10 августа 2022 г.
- ^ oracle.com Руководство по языку Java по автобоксу