Что упаковывает и распаковывает и какова торговля offs?

Недавно я использовал это для мобильного сайта. Это упрощенная версия Джона Ресига из «Pro JavaScript Techniques». Это зависит от addEvent.

var ready = ( function () {
  function ready( f ) {
    if( ready.done ) return f();

    if( ready.timer ) {
      ready.ready.push(f);
    } else {
      addEvent( window, "load", isDOMReady );
      ready.ready = [ f ];
      ready.timer = setInterval(isDOMReady, 13);
    }
  };

  function isDOMReady() {
    if( ready.done ) return false;

    if( document && document.getElementsByTagName && document.getElementById && document.body ) {
      clearInterval( ready.timer );
      ready.timer = null;
      for( var i = 0; i < ready.ready.length; i++ ) {
        ready.ready[i]();
      }
      ready.ready = null;
      ready.done = true;
    }
  }

  return ready;
})();
127
задан James McMahon 27 November 2009 в 19:06
поделиться

6 ответов

Помещенные в коробку значения структуры данных , которые являются минимальными обертками приблизительно типы примитивов *. Помещенные в коробку значения обычно хранятся как указатели на объекты на "куча" .

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

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

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

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

** я также фокусируюсь на Java, Haskell и C# в этом ответе, потому что это - то, что я знаю. Если это имеет значение, Python, Ruby и JavaScript все исключительно упаковали значения. Это также известно как, "Все - объект", приближаются к ***.

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

181
ответ дан 24 November 2019 в 00:41
поделиться

от C# 3.0 Вкратце :

Упаковка является действием кастинга типа значения в ссылочный тип:

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

распаковывание является... реверсом:

// unboxing o
object o = 9; 
int x = (int)o; 
124
ответ дан 24 November 2019 в 00:41
поделиться

В .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

Однако это - другая вещь остерегаться при контакте с помещенными в коробку значениями.

23
ответ дан 24 November 2019 в 00:41
поделиться

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

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

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

В эти дни, это обычно обсуждено в контексте Java (и другой язык) "автоупаковка/автораспаковывание" функции. Вот Java центральное объяснение автоупаковки .

71
ответ дан 24 November 2019 в 00:41
поделиться

Универсальные наборы FCL.NET:

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

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

Для больше, см. главу 16, CLR через C# (2-й Выпуск) .

3
ответ дан 24 November 2019 в 00:41
поделиться

Как что-либо еще, автоупаковка может быть проблематичной если не используемый тщательно. Классик должен закончить с 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;
    }
}
-2
ответ дан 24 November 2019 в 00:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: