Эта статья поднимает множество проблем. Пожалуйста, помогите улучшить его или обсудите эти проблемы на странице обсуждения . ( Узнайте, как и когда удалить эти сообщения-шаблоны ) ( Узнайте, как и когда удалить этот шаблон сообщения )
|
В информатике , тип объекта ( так называемый объект оберточной ) является тип данных , который используется в объектно-ориентированном программировании , чтобы обернуть тип не-объект , чтобы сделать его похожим на динамический объект . [ необходима цитата ]
Некоторые объектно-ориентированные языки программирования делают различие между ссылочными типами и типами значений , часто называемыми объектами и не-объектами на платформах, где сложные типы значений не существуют, по таким причинам, как эффективность времени выполнения и синтаксические или семантические проблемы. Например, в Java есть классы-оболочки-примитивы, соответствующие каждому примитивному типу : Integer
and int
, Character
and char
, Float
and и float
т. Д. Такие языки, как C ++ , почти или совсем не имеют понятия ссылочного типа ; таким образом, использование типа объекта не представляет особого интереса.
Бокс [ править ]
Упаковка, также известная как упаковка, - это процесс помещения примитивного типа в объект, чтобы этот примитив можно было использовать в качестве ссылочного объекта. Например, в Java a LinkedList
может изменять свой размер, но массив должен иметь фиксированный размер. Кто-то может пожелать иметь LinkedList
из int
, но LinkedList
класс перечисляет только ссылки на динамические объекты - он не может перечислять примитивные типы, которые являются типами значений.
Чтобы обойти это, int
можно поместить в блоки Integer
, которые являются динамическими объектами, а затем добавить в LinkedList
из Integer
. (Используя универсальные параметризованные типы, представленные в J2SE 5.0, этот тип представлен как .) С другой стороны, C # не имеет примитивных классов-оболочек, но позволяет упаковывать любой тип значения, возвращая универсальную ссылку. В Objective-C к любому примитивному значению может быть добавлен префикс " }" (например, или ). Это позволяет добавлять их в любую из стандартных коллекций, например в .LinkedList<Integer>
Object
@
NSNumber
@123
@(123)
NSArray
Упакованный объект всегда является копией объекта значения и обычно неизменяем . Распаковка объекта также возвращает копию сохраненного значения. Повторная упаковка и распаковка объектов может иметь серьезное влияние на производительность, потому что упаковка динамически выделяет новые объекты, а распаковка (если упакованное значение больше не используется) делает их пригодными для сборки мусора . Однако современные сборщики мусора, такие как сборщик мусора Java HotSpot по умолчанию, могут более эффективно собирать недолговечные объекты, поэтому, если объекты в штучной упаковке недолговечны, влияние на производительность может быть не таким уж плохим.
В некоторых языках существует прямая эквивалентность между распакованным примитивным типом и ссылкой на неизменяемый упакованный объектный тип. Фактически, можно заменить все примитивные типы в программе упакованными типами объектов. В то время как присвоение одного примитива другому будет копировать его значение, присвоение из одной ссылки помещенному в коробку объекту другому скопирует значение ссылки для ссылки на тот же объект, что и первая ссылка. Однако это не вызовет никаких проблем, потому что объекты неизменяемы, поэтому семантически нет реальной разницы между двумя ссылками на один и тот же объект или на разные объекты (если вы не смотрите на физическое равенство). Для всех операций, кроме присваивания, таких как арифметика, сравнение и логические операторы, можно распаковать упакованный тип, выполнить операцию и повторно упаковать результат по мере необходимости.Таким образом, можно вообще не хранить примитивные типы.
Автобокс [ править ]
Автобоксирование - это термин, обозначающий получение ссылочного типа из типа значения только посредством преобразования типа (неявного или явного). Компилятор автоматически предоставляет дополнительный исходный код, который создает объект.
Например, в версиях Java до J2SE 5.0 следующий код не компилировался:
Целое число i = новое целое число ( 9 ); Целое число i = 9 ; // ошибка в версиях до 5.0!
Компиляторы до 5.0 не принимали последнюю строку. Integer
не являются контрольными объектами, на поверхности не отличается от List
, Object
и так далее. Чтобы преобразовать из an int
в an Integer
, нужно было «вручную» создать экземпляр объекта Integer. Начиная с J2SE 5.0, компилятор примет последнюю строку и автоматически преобразует ее, чтобы создать объект Integer для хранения значения 9
. [1] Это означает, что, начиная с J2SE 5.0 и далее, что-то вроде , where и are сами по себе, теперь будет компилироваться - a и b распакованы, целочисленные значения суммируются, а результат автоматически упаковывается в новое , которое, наконец, сохраняется внутри ПеременнаяInteger c = a + b
a
b
Integer
Integer
c
. Операторы равенства не могут использоваться таким образом, потому что операторы равенства уже определены для ссылочных типов, для равенства ссылок; чтобы проверить равенство значений в упакованном типе, нужно вручную распаковать их и сравнить примитивы или использовать метод.Objects.equals
Другой пример: J2SE 5.0 позволяет программисту обрабатывать коллекцию (например, a LinkedList
) так, как если бы она содержала int
значения вместо Integer
объектов. Это не противоречит сказанному выше: коллекция по-прежнему содержит только ссылки на динамические объекты и не может перечислять примитивные типы. Это не может быть , но вместо этого он должен быть . Однако компилятор автоматически преобразует код так, что список будет «незаметно» получать объекты, в то время как исходный код упоминает только примитивные значения. Например, теперь программист может писать и думать так, как если бы они были добавлены в список; но компилятор фактически преобразовал строку в .LinkedList<int>
LinkedList<Integer>
list.add(3)
int
3
list.add(new Integer(3))
Распаковка [ править ]
Распаковка относится к получению значения, связанного с данным объектом, просто посредством преобразования типа (неявного или явного). Компилятор автоматически предоставляет дополнительный исходный код, который извлекает значение из этого объекта, либо вызывая какой-либо метод для этого объекта, либо другими способами.
Например, в версиях Java до J2SE 5.0 следующий код не компилировался:
Целое число k = новое целое число ( 4 ); int l = k . intValue (); // всегда нормально int m = k ; // было бы ошибкой, но теперь ладно
C # не поддерживает автоматическую распаковку в том же смысле, что и Java, потому что в нем нет отдельного набора примитивных типов и типов объектов. Все типы, которые в Java имеют как примитивную, так и объектную версию, автоматически реализуются компилятором C # как либо примитивные (значения), либо как объектные (ссылочные) типы.
На обоих языках автоматическая упаковка не выполняется автоматически, т. Е. Следующий код не компилируется:
C #:
int i = 42 ; объект o = i ; // коробка int j = o ; // распаковка (ошибка) Console . WriteLine ( j ); // недостижимая строка, автор мог ожидать вывода "42"
Ява:
int i = 42 ; Объект o = i ; // коробка int j = o ; // распаковка (ошибка) System . из . println ( j ); // недостижимая строка, автор мог ожидать вывода "42"
Помощники по типу [ править ]
В Modern Object Pascal есть еще один способ выполнения операций с простыми типами, близкий к боксу, называемый помощниками типов в FreePascal или помощниками записи в Delphi и FreePascal в режиме Delphi.
Упомянутые диалекты являются языками компиляции Object Pascal для нативных языков, поэтому в них отсутствуют некоторые функции, которые могут реализовать C # и Java. В частности, вывод типа во время выполнения для строго типизированных переменных.
Но особенность связана с боксом.
Это позволяет программисту использовать такие конструкции, как
{$ ifdef fpc} {$ mode delphi} {$ endif} использует sysutils ; // этот блок содержит обертки для простых типов var x : integer = 100 ; s : строка ; начало s : = x . ToString ; Writeln ( s ) ; конец .
Ссылки [ править ]
- ^ oracle.com статья в руководстве по языку Java по автобоксу