stringtranslate.com

Бокс (информатика)

В информатике упаковка (также известная как упаковка) — это преобразование размещения примитивного типа внутри объекта так, чтобы значение можно было использовать в качестве ссылки . Распаковка — это обратное преобразование извлечения примитивного значения из объекта-оболочки. Автоупаковка — это термин, обозначающий автоматическое применение преобразований упаковки и/или распаковки по мере необходимости.

Заниматься боксом

Наиболее заметное использование бокса приходится на Java , где существует различие между ссылочными типами и типами значений по таким причинам, как эффективность выполнения, а также синтаксические и семантические проблемы. В Java a LinkedListможет хранить только значения типа Object. Можно было бы захотеть иметь LinkedListof int, но это невозможно напрямую. Вместо этого Java определяет примитивные классы-оболочки , соответствующие каждому примитивному типу : Integerand int, Characterand char, Floatand floatи т. д. Затем можно определить a, LinkedListиспользуя упакованный тип Integer, и вставить intзначения в список, упаковав их как Integerобъекты. (При использовании универсальных параметризованных типов, представленных в J2SE 5.0, этот тип представляется как .)LinkedList<Integer>

С другой стороны, C# не имеет примитивных классов-оболочек, но позволяет упаковывать значения любого типа, возвращая общую Objectссылку. В Objective-C любое примитивное значение может иметь префикс a, чтобы из него @получилось (например, или ). Это позволяет добавлять их в любую стандартную коллекцию, например в файл .NSNumber@123@(123)NSArray

В Haskell практически нет понятия ссылочного типа , но он по-прежнему использует термин «коробочный» для унифицированного представления объединения указателей на теги в системе времени выполнения . [1]

Упакованный объект всегда является копией объекта значения и обычно является неизменяемым . Распаковка объекта также возвращает копию сохраненного значения. Повторяющаяся упаковка и распаковка объектов может оказать серьезное влияние на производительность, поскольку упаковка динамически выделяет новые объекты, а распаковка (если упакованное значение больше не используется) делает их пригодными для сборки мусора . Однако современные сборщики мусора, такие как сборщик мусора Java HotSpot по умолчанию, могут более эффективно собирать недолговечные объекты, поэтому, если упакованные объекты недолговечны, влияние на производительность может быть не таким серьезным.

В некоторых языках существует прямая эквивалентность между неупакованным примитивным типом и ссылкой на неизменяемый упакованный тип объекта. Фактически, все примитивные типы в программе можно заменить коробочными типами объектов. В то время как присвоение одного примитива другому копирует его значение, присвоение одной ссылки на упакованный объект другому копирует значение ссылки для ссылки на тот же объект, что и первая ссылка. Однако это не вызовет никаких проблем, поскольку объекты неизменяемы, поэтому семантически нет реальной разницы между двумя ссылками на один и тот же объект или на разные объекты (если только вы не посмотрите на физическое равенство). Для всех операций, кроме присваивания, таких как арифметические операции, сравнения и логические операторы, можно распаковать упакованный тип, выполнить операцию и повторно упаковать результат по мере необходимости. Таким образом, можно вообще не хранить примитивные типы.

Автобокс

Автоупаковка — это термин, обозначающий получение ссылочного типа из типа значения только посредством преобразования типа (неявного или явного). Компилятор автоматически предоставляет дополнительный исходный код, создающий объект.

Например, в версиях Java до J2SE 5.0 следующий код не компилировался:

Целое число i = новое целое число ( 9 ); Целое число я = 9 ; // ошибка в версиях до 5.0!        

Компиляторы до версии 5.0 не принимали последнюю строку. Integerявляются эталонными объектами, на первый взгляд ничем не отличающимися от List, Object, и т.д. Чтобы преобразовать a в inta Integer, нужно было «вручную» создать экземпляр объекта Integer. Начиная с J2SE 5.0, компилятор принимает последнюю строку и автоматически преобразует ее так, что для хранения значения создается объект Integer 9. [2] Это означает, что начиная с J2SE 5.0 что-то вроде , где и сами по себе, теперь будет компилироваться - a и b распаковываются, целочисленные значения суммируются, а результат автоматически упаковывается в новый , который, наконец, сохраняется внутри переменная . Операторы равенства нельзя использовать таким образом, поскольку операторы равенства уже определены для ссылочных типов, для равенства ссылок; чтобы проверить равенство значения в коробочном типе, все равно необходимо вручную распаковать их и сравнить примитивы или использовать этот метод.Integer c = a + babIntegerIntegercObjects.equals

Другой пример: J2SE 5.0 позволяет программисту обращаться с коллекцией (например, LinkedList), как если бы она содержала intзначения, а не Integerобъекты. Это не противоречит сказанному выше: коллекция по-прежнему содержит только ссылки на динамические объекты и не может перечислять примитивные типы. Это не может быть , но вместо этого это должно быть . Однако компилятор автоматически преобразует код так, что список будет «тихо» получать объекты, тогда как в исходном коде упоминаются только примитивные значения. Например, программист теперь может писать и думать так, как если бы они были добавлены в список; но компилятор фактически преобразует строку в .LinkedList<int>LinkedList<Integer>list.add(3)int 3list.add(new Integer(3))

Автоматическая распаковка

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

Например, в версиях Java до J2SE 5.0 следующий код не компилировался:

Целое число k = новое целое число ( 4 ); интервал л знак равно k . intЗначение (); // всегда в порядке int m = k ; // это было бы ошибкой, но сейчас все в порядке            

C# не поддерживает автоматическую распаковку в том же смысле, что и Java, поскольку в нем нет отдельного набора примитивных типов и типов объектов. Все типы, которые в Java имеют как примитивную, так и объектную версию, автоматически реализуются компилятором C# либо как примитивные (значения), либо как объектные (ссылочные) типы.

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

С#:

интервал я = 42 ; объект о = я ; // поле int j = o ; // распаковка (ошибка) Консоль . WriteLine ( j ); // недоступная строка, автор мог ожидать вывода "42"            

Джава:

интервал я = 42 ; Объект о = я ; // поле int j = o ; // распаковка (ошибка) Система . вне . печатьln ( j ); // недоступная строка, автор мог ожидать вывода "42"            

Введите помощники

В современном Object Pascal есть еще один способ выполнения операций над простыми типами, близкий к упаковке, который называется помощниками типов во FreePascal или помощниками записи в Delphi и FreePascal в режиме Delphi.
Упомянутые диалекты представляют собой языки, компилируемые в собственный язык Object Pascal, и поэтому в них отсутствуют некоторые возможности, которые могут реализовать C# и Java. В частности, выведение типа во время выполнения для строго типизированных переменных.
Но особенность связана с боксом.
Это позволяет программисту использовать такие конструкции, как

{$ifdef fpc}{$mode delphi}{$endif} использует sysutils ; // этот модуль содержит обертки для простых типов var x : целое число = 100 ; с : строка ; начать s := x . Нанизывать ; записьln ( s ) ; конец .       

Рекомендации

  1. ^ «7.2. Распакованные типы и примитивные операции». downloads.haskell.org . Проверено 10 августа 2022 г.
  2. ^ oracle.com Руководство по языку Java по автобоксу