Сведения о вопросе

Solllo

06:59, 20th August, 2020

Теги

Что такое бокс и распаковка и каковы компромиссы?

Просмотров: 421   Ответов: 8

Я ищу ясный, лаконичный и точный ответ.

В идеале в качестве фактического ответа, хотя ссылки на хорошие объяснения приветствуются.



  Сведения об ответе

DINO

02:58, 13th August, 2020

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

Таким образом, упакованные значения используют больше памяти и требуют как минимум двух поисков памяти для доступа: один раз, чтобы получить указатель, и другой, чтобы следовать за этим указателем к примитиву. Очевидно, что это не та вещь, которую вы хотите видеть в своих внутренних петлях. С другой стороны, коробочные значения обычно лучше работают с другими типами в системе. Поскольку они являются первоклассными структурами данных в языке, они имеют ожидаемые метаданные и структуру, которые имеют другие структуры данных.

В универсальных коллекциях Java и Haskell не могут содержаться распакованные значения. Универсальные коллекции в .NET могут содержать распакованные значения без штрафных санкций. Если универсальные типы Java используются только для проверки типов во время компиляции, то .NET будет генерировать определенные классы для каждого универсального типа, созданного во время выполнения .

Java и Haskell имеют распакованные массивы, но они явно менее удобны, чем другие коллекции. Однако, когда требуется пиковая производительность, стоит немного неудобств, чтобы избежать накладных расходов на бокс и распаковку.

* Для данного обсуждения примитивным значением является любое значение, которое может быть сохранено в стеке вызовов, а не сохранено как указатель на значение в куче. Часто это просто типы машин (ints, floats и т. д.), структуры, а иногда и массивы статического размера. .NET-land называет их типами значений (в отличие от ссылочных типов). Люди называют их примитивными типами. Хаскеллионы просто называют их распакованными.

** Я также сосредотачиваюсь на Java, Haskell и C# в этом ответе, потому что это то, что я знаю. Как бы то ни было, Python, Ruby и Javascript имеют исключительно коробочные значения. Это также известно как "Everything is an object" approach***.

*** Предостережение: достаточно продвинутый компилятор / JIT может в некоторых случаях действительно обнаружить, что значение, которое семантически упаковано при взгляде на источник, может безопасно быть распакованным значением во время выполнения. По сути, благодаря блестящим языковым реализаторам ваши ящики иногда свободны.


  Сведения об ответе

dump

13:42, 3rd August, 2020

от C# 3.0 в двух словах :

Бокс-это акт подбрасывания ценности введите в ссылочный тип:

int x = 9; 
object o = x; // boxing the int

распаковка есть... реверс:

// unboxing o
object o = 9; 
int x = (int)o; 


  Сведения об ответе

padenie

14:36, 21st August, 2020

Boxing & распаковка-это процесс преобразования примитивного значения в объектно-ориентированный класс-оболочку (boxing) или преобразования значения из объектно-ориентированного класса-оболочки обратно в примитивное значение (unboxing).

Например, в java вам может потребоваться преобразовать значение int в Integer (бокс), если вы хотите сохранить его в Collection , потому что примитивы не могут быть сохранены в Collection, только объекты. Но когда вы хотите получить его обратно из Collection , вы можете получить значение как int , а не Integer , чтобы распаковать его.

Бокс и распаковка не являются изначально плохими, но это компромисс. В зависимости от языковой реализации он может быть медленнее и более интенсивным, чем просто использование примитивов. Однако это также может позволить вам использовать структуры данных более высокого уровня и добиться большей гибкости в коде.

В наши дни он чаще всего обсуждается в контексте функции Java (и других языков) "autoboxing/autounboxing". Вот java-центрическое объяснение автобоксинга .


  Сведения об ответе

SILA

01:40, 23rd August, 2020

в сетях:

Часто вы не можете полагаться на то, какой тип переменной будет потреблять функция, поэтому вам нужно использовать объектную переменную, которая простирается от самого низкого общего знаменателя - в .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

Однако совсем другое дело-быть осторожным, когда имеешь дело с коробочными ценностями.


  Сведения об ответе

9090

14:50, 1st August, 2020

В .NET FCL универсальных коллекций:

List<T>
Dictionary<TKey, UValue>
SortedDictionary<TKey, UValue>
Stack<T>
Queue<T>
LinkedList<T>

все они были разработаны для преодоления проблем производительности бокса и распаковки в предыдущих реализациях коллекции.

Подробнее см. Главу 16, CLR-C# (2-е издание) .


  Сведения об ответе

padenie

20:18, 4th August, 2020

Бокс - это процесс преобразования типа значения в ссылочный тип.

Распаковка-это преобразование ссылочного типа в тип значения.

EX: int i=123;
    object o=i;// Boxing
    int j=(int)o;// UnBoxing

Тип значения являются:
int, char и структуры, перечисления. Ссылочным типом являются: Классы, интерфейсы, массивы, строки и объекты


  Сведения об ответе

#hash

19:10, 2nd August, 2020

Бокс и распаковка облегчают обработку типов значений как объектов. Бокс означает преобразование значения в экземпляр ссылочного типа объекта. Например, Int - это класс, а int -тип данных. Преобразование int в Int -это пример бокса, в то время как преобразование Int в int -это распаковка. Концепция помогает в сборке мусора, распаковке, с другой стороны, преобразует тип объекта в тип значения.

int i=123;
object o=(object)i; //Boxing

o=123;
i=(int)o; //Unboxing.


  Сведения об ответе

SEEYOU

14:13, 7th August, 2020

Как и все остальное, автобоксинг может быть проблематичным, если не использовать его тщательно. Классика заключается в том, чтобы в конечном итоге получить 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;
    }
}


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться