Ищу ясный, лаконичный и точный ответ.
В идеале как фактический ответ, хотя ссылки на хорошие объяснения приветствуются.
Ищу ясный, лаконичный и точный ответ.
В идеале как фактический ответ, хотя ссылки на хорошие объяснения приветствуются.
Значения в рамке - это структуры данных, которые представляют собой минимальные оболочки вокруг примитивные типы *. Упакованные значения обычно хранятся как указатели на объекты в куче.
Таким образом, упакованные значения используют больше памяти и требуют как минимум двух поисков в памяти для доступа: один раз для получения указателя, а другой - для отслеживания этого указателя на примитив. Очевидно, это не то, что вам нужно во внутренних циклах. С другой стороны, значения в штучной упаковке обычно лучше работают с другими типами в системе. Поскольку они являются первоклассными структурами данных на языке, они имеют ожидаемые метаданные и структуру, которые имеют другие структуры данных.
В Java и Haskell общие коллекции не могут содержать неупакованные значения. Общие коллекции в .NET могут содержать неупакованные значения без каких-либо штрафов. Если универсальные шаблоны Java используются только для проверки типов во время компиляции, .NET будет сгенерировать определенные классы для каждого универсального типа, созданного во время выполнения.
В Java и Haskell есть распакованные массивы, но они явно менее удобны, чем другие коллекции. Однако, когда необходима максимальная производительность, стоит доставить небольшое неудобство, чтобы избежать накладных расходов на упаковку и распаковку.
* В данном обсуждении примитивным значением является любое значение, которое может храниться в стеке вызовов, а не хранится как указатель на значение в куче. Часто это просто типы машин (целые числа, числа с плавающей запятой и т. Д.), Структуры, а иногда и массивы статического размера. .NET-land называет их типами значений (в отличие от ссылочных типов). Люди, занимающиеся Java, называют их примитивными типами. Хаскеллионы просто называют их распакованными.
** В этом ответе я также сосредоточусь на Java, Haskell и C #, потому что это то, что я знаю. Как бы то ни было, Python, Ruby и Javascript имеют исключительно упакованные значения. Это также известно как подход «Все является объектом» ***.
*** Предостережение: достаточно продвинутый компилятор / JIT может в некоторых случаях фактически обнаружить, что значение, которое семантически упаковано при просмотре источника, может безопасно быть распакованным значением во время выполнения. По сути, благодаря блестящим разработчикам языка ваши боксы иногда бесплатны.
из :
Упаковка - это акт преобразования типа значения в ссылочный тип:
int x = 9;
object o = x; // boxing the int
распаковка ... наоборот:
// unboxing o
object o = 9;
int x = (int)o;
Упаковка и распаковка - это процесс преобразования примитивного значения в объектно-ориентированный класс-оболочка (упаковка) или преобразования значения из объектно-ориентированного класса-оболочки обратно в примитивное значение (распаковка).
Например, в java вам может потребоваться преобразовать значение int в Integer (бокс), если вы хотите сохранить его в Collection, потому что примитивы не могут храниться в Collection, только в объектах. Но если вы захотите вернуть его из Collection, вы можете получить значение как int, а не Integer, чтобы распаковать его.
Упаковка и распаковка по своей сути не являются плохими, но это компромисс. В зависимости от языковой реализации это может быть медленнее и потреблять больше памяти, чем просто использование примитивов. Однако это также может позволить вам использовать структуры данных более высокого уровня и добиться большей гибкости в вашем коде.
В наши дни это чаще всего обсуждается в контексте функции «autoboxing / autounboxing» Java (и других языков). Вот java-ориентированное объяснение автобокса.
В .Net:
Часто вы не можете полагаться на тип переменной, которую будет использовать функция, поэтому вам нужно использовать объектную переменную, которая начинается с наименьшего общего знаменателя - в .Net это object.
Однако object является классом и хранит свое содержимое как ссылку.
List<int> notBoxed = new List<int> { 1, 2, 3 };
int i = notBoxed[1]; // this is the actual value
List<object> boxed = new List<object> { 1, 2, 3 };
int j = (int) boxed[1]; // this is an object that can be 'unboxed' to an int
Хотя оба они содержат одинаковую информацию, второй список больше и медленнее. Каждое значение во втором списке на самом деле является ссылкой на object, который содержит int.
Это называется упакованным в коробку, потому что int обернут object. При возврате int распаковывается - конвертируется обратно в свое значение.
Для типов значений (т.е. всех structs) это медленно и потенциально требует гораздо больше места.
Для ссылочных типов (то есть всех classes) это гораздо меньшая проблема, поскольку они в любом случае сохраняются как ссылки.
Еще одна проблема с типом значения в штучной упаковке заключается в том, что не очевидно, что вы имеете дело с блоком, а не со значением. Когда вы сравниваете два structs, вы сравниваете значения, но когда вы сравниваете два classes, тогда (по умолчанию) вы сравниваете эталон, то есть это один и тот же экземпляр?
Это может сбивать с толку при работе с типами значений в штучной упаковке:
int a = 7;
int b = 7;
if(a == b) // Evaluates to true, because a and b have the same value
object c = (object) 7;
object d = (object) 7;
if(c == d) // Evaluates to false, because c and d are different instances
Легко обойти:
if(c.Equals(d)) // Evaluates to true because it calls the underlying int's equals
if(((int) c) == ((int) d)) // Evaluates to true once the values are cast
Однако при работе со значениями в штучной упаковке следует соблюдать осторожность.
Object не реализует оператор равенства, но типы классов можно сравнивать с оператором Is; и наоборот, Int32 можно использовать с оператором равенства, но не Is. Это различие проясняет, какой тип сравнения проводится.
- person supercat; 08.12.2012
Boxing - это процесс преобразования типа значения в ссылочный тип. В то время как Unboxing - это преобразование ссылочного типа в тип значения.
EX: int i = 123;
object o = i;// Boxing
int j = (int)o;// UnBoxing
Типы значений: int, char и structures, enumerations. Типы ссылок: _8 _, _ 9 _, _ 10 _, _ 11_ и objects
Общие коллекции .NET FCL:
List<T>
Dictionary<TKey, UValue>
SortedDictionary<TKey, UValue>
Stack<T>
Queue<T>
LinkedList<T>
все были разработаны для решения проблем производительности упаковки и распаковки в предыдущих реализациях коллекции.
Подробнее см. Главу 16, CLR через C # (2-е издание).
Упаковка и распаковка упрощают обработку типов значений как объектов. Упаковка означает преобразование значения в экземпляр ссылочного типа на объект. Например, Int - это класс, а int - тип данных. Преобразование int в Int является примером бокса, тогда как преобразование Int в int - это распаковка. Эта концепция помогает при сборке мусора, а распаковка преобразует тип объекта в тип значения.
int i=123;
object o=(object)i; //Boxing
o=123;
i=(int)o; //Unboxing.
var ii = 123; typeof ii возвращает number. var iiObj = new Number(123); typeof iiObj возвращает object. typeof ii + iiObj возвращает number. Так что это эквивалент бокса в javascript. Значение iiObj было автоматически преобразовано в примитивное число (распакованное), чтобы выполнить арифметику и вернуть распакованное значение.
- person PatS; 19.11.2018
Как и все остальное, автобоксинг может быть проблематичным, если его не использовать осторожно. Классический вариант - получить исключение NullPointerException и не удастся его отследить. Даже с отладчиком. Попробуй это:
public class TestAutoboxNPE
{
public static void main(String[] args)
{
Integer i = null;
// .. do some other stuff and forget to initialise i
i = addOne(i); // Whoa! NPE!
}
public static int addOne(int i)
{
return i + 1;
}
}
i инициализирована преждевременно. Либо сделайте его пустым объявлением (Integer i;), чтобы компилятор мог указать, что вы забыли его инициализировать, либо подождите, чтобы объявить его, пока вы не узнаете его значение.
- person erickson; 25.09.2008
language-but-not-type-agnostic?static-language-agnostic? Я не уверен, что SO нужно различие; может быть хорошим вопросом для меты. - person Keith   schedule 29.10.2012