Почему некоторым языкам нужны Упаковка и Распаковывание?

Гораздо проще:

#!/bin/sh
type apt-cyg || exit
apt-cyg install git python-{jinja2,six,yaml}
git clone --depth 1 git://github.com/ansible/ansible
cd ansible
PATH+=:~+/bin
export PYTHONPATH=~+/lib
ansible --version

Результат

ansible 2.0.0 (devel 2a50957ad8) last updated 2015/09/15 21:22:17 (GMT -500)
30
задан AraK 24 June 2009 в 19:19
поделиться

5 ответов

что так сложно технически включить примитивные типы при разговоре о универсальных типах?

В случае Java это из-за того, как работают универсальные типы. В Java универсальные шаблоны - это уловка во время компиляции, которая не позволяет вам помещать объект Image в ArrayList . Однако универсальные типы Java реализуются со стиранием типа: информация об общем типе теряется во время выполнения. Это было сделано из соображений совместимости, потому что дженерики были добавлены довольно поздно в жизни Java. Это означает, что во время выполнения ArrayList фактически является ArrayList (или лучше: просто ArrayList , который ожидает и возвращает Object во всех своих методах), который автоматически приводит к String , когда вы извлекаете значение.

Но поскольку int не является производным от Object , вы не можете поместить его в ArrayList, который ожидает (во время выполнения) Object , и вы можете 'также не приводил Object к int . Это означает, что примитив int должен быть заключен в тип, который наследуется от Object , например Integer .

Например, C # работает иначе. Обобщения в C # также применяются во время выполнения, и упаковка List не требуется. Упаковка в C # происходит только тогда, когда вы пытаетесь сохранить тип значения, такой как int , в переменной ссылочного типа, такой как object . Поскольку int в C # наследуется от Object в C #, запись object obj = 2 вполне допустима, однако int будет заключен в рамку, что автоматически выполняется компилятор (нет Целочисленный ссылочный тип, доступный пользователю или чему-либо еще).

50
ответ дан 27 November 2019 в 23:31
поделиться

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

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

Во-вторых, главная причина не включать это было то, что они хотели двоичной обратной совместимости, чтобы она работала без изменений на виртуальной машине, не знающей обобщений. Эта причина обратной совместимости / совместимости миграции также является причиной того, что теперь API-интерфейс Collections поддерживает дженерики и остался прежним, и нет (как в C #, когда они ввели дженерики) полного нового набора универсального API-интерфейса Collection.

Совместимость была достигнута с помощью ersure (общая информация о параметрах типа удалена во время компиляции), что также является причиной того, что вы получаете так много непроверенных предупреждений о приведении типов в java.

Вы все еще можете добавить усовершенствованные дженерики, но это не так просто. Простое добавление информации о типе add runtime вместо удаления не будет работать, так как это нарушает работу исходного кода & amp; бинарная совместимость (вы не можете продолжать использовать необработанные типы и не можете вызывать существующий скомпилированный код, потому что у них нет соответствующих методов).

Другой подход - тот, который выбрал C #: см. Выше

И автоматическая автобокс / распаковка не поддерживалась для этого варианта использования, потому что автобокс стоит слишком дорого.

Теория и практика Java: общие сведения о гтчах

2
ответ дан jitter 11 October 2019 в 13:14
поделиться

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

Некоторые типы размещаются в стеке, а другие - в куче. Чтобы рассматривать тип, выделенный из стека, как тип, выделенный из кучи, бокс должен перемещать тип, выделенный из стека, в кучу. Распаковка происходит в обратном порядке.

В C # типы, выделенные для стека, называются типами значений (например, System.Int32 и System.DateTime), а типы, выделенные в куче, называются ссылочными типами (например, System.Stream и System.String).

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

12
ответ дан Andrew Hare 11 October 2019 в 13:14
поделиться

В Java и C # (в отличие от C ++) все расширяет Object, поэтому классы коллекций, такие как ArrayList, могут содержать Object или любого из его потомков (в основном что угодно).

Однако по соображениям производительности примитивам в Java или типам значений в C # был присвоен особый статус. Они не объект. Вы не можете сделать что-то вроде (в Java):

 7.toString()

, хотя toString является методом для Object. Для того, чтобы связать этот узел с производительностью, были созданы эквивалентные объекты. AutoBoxing удаляет стандартный код необходимости помещать примитив в его класс-обертку и извлекать его снова, делая код более читабельным.

Разница между типами значений и объектами в C # более серая. См. здесь о том, как они отличаются.

1
ответ дан Yishai 11 October 2019 в 13:14
поделиться

I believe this is also because primitives do not inherit from Object. Suppose you have a method that wants to be able to accept anything at all as the parameter, eg.

class Printer {
    public void print(Object o) {
        ...
    }
}

You may need to pass a simple primitive value to that method, like:

printer.print(5);

You would be able to do that without boxing/unboxing, because 5 is a primitive and is not an Object. You could overload the print method for each primitive type to enable such functionality, but it's a pain.

2
ответ дан 27 November 2019 в 23:31
поделиться
Другие вопросы по тегам:

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