stringtranslate.com

Бокс (компьютерное программирование)

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

Бокс

Наиболее заметное применение упаковки — в Java , где существует различие между ссылочными и значимыми типами по таким причинам, как эффективность выполнения, а также синтаксические и семантические проблемы. В Java a LinkedListможет хранить только значения типа Object. Можно было бы захотеть иметь a LinkedListиз int, но это напрямую невозможно. Вместо этого Java определяет примитивные классы-оболочки, соответствующие каждому примитивному типу : Integerи int, Characterи char, Floatи 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 следующий код не компилировался:

Integer i = new Integer ( 9 ); Integer i = 9 ; // ошибка в версиях до 5.0!        

Компиляторы до версии 5.0 не принимали последнюю строку. Integerявляются ссылочными объектами, на первый взгляд ничем не отличающимися от List, Objectи так далее. Чтобы преобразовать из в int, 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 следующий код не компилировался:

Integer k = new Integer ( 4 ); int l = k . intValue (); // всегда хорошо int m = k ; // было бы ошибкой, но сейчас все в порядке            

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

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

С#:

int i = 42 ; object o = i ; // box int j = o ; // unbox (ошибка) Console . WriteLine ( j ); // недостижимая строка, автор мог ожидать вывода "42"            

Ява:

int i = 42 ; Object o = i ; // box int j = o ; // unbox (ошибка) System.out.println ( j ) ; // недостижимая строка , автор мог ожидать вывода "42 "            

Помощники по типам

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

{ $ifdef fpc}{$mode delphi}{$endif} использует sysutils ; // этот модуль содержит оболочки для простых типов var x : integer = 100 ; s : string ; begin s : = x.ToString ; writeln ( s ) ; end .       

Ссылки

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