Гораздо проще:
#!/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)
что так сложно технически включить примитивные типы при разговоре о универсальных типах?
В случае 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 будет заключен в рамку, что автоматически выполняется компилятор (нет Целочисленный
ссылочный тип, доступный пользователю или чему-либо еще).
Я могу только сказать вам для Java, почему он не поддерживает типы примитивов в дженериках.
Сначала возникла проблема, заключающаяся в том, что вопрос о том, чтобы поддерживать это каждый раз, вызывал дискуссию о том, должны ли Java иметь примитивные типы. Что, конечно, мешало обсуждению актуального вопроса.
Во-вторых, главная причина не включать это было то, что они хотели двоичной обратной совместимости, чтобы она работала без изменений на виртуальной машине, не знающей обобщений. Эта причина обратной совместимости / совместимости миграции также является причиной того, что теперь API-интерфейс Collections поддерживает дженерики и остался прежним, и нет (как в C #, когда они ввели дженерики) полного нового набора универсального API-интерфейса Collection.
Совместимость была достигнута с помощью ersure (общая информация о параметрах типа удалена во время компиляции), что также является причиной того, что вы получаете так много непроверенных предупреждений о приведении типов в java.
Вы все еще можете добавить усовершенствованные дженерики, но это не так просто. Простое добавление информации о типе add runtime вместо удаления не будет работать, так как это нарушает работу исходного кода & amp; бинарная совместимость (вы не можете продолжать использовать необработанные типы и не можете вызывать существующий скомпилированный код, потому что у них нет соответствующих методов).
Другой подход - тот, который выбрал C #: см. Выше
И автоматическая автобокс / распаковка не поддерживалась для этого варианта использования, потому что автобокс стоит слишком дорого.
Упаковка и распаковка являются необходимостью, обусловленной тем, как языки (такие как C # и Java) реализуют свои стратегии распределения памяти.
Некоторые типы размещаются в стеке, а другие - в куче. Чтобы рассматривать тип, выделенный из стека, как тип, выделенный из кучи, бокс должен перемещать тип, выделенный из стека, в кучу. Распаковка происходит в обратном порядке.
В C # типы, выделенные для стека, называются типами значений (например, System.Int32
и System.DateTime
), а типы, выделенные в куче, называются ссылочными типами (например, System.Stream
и System.String
).
В некоторых случаях выгодно иметь возможность обрабатывать тип значения как ссылочный тип (одним из примеров является отражение), но в большинстве случаев лучше избегать упаковки и распаковки.
В Java и C # (в отличие от C ++) все расширяет Object, поэтому классы коллекций, такие как ArrayList, могут содержать Object или любого из его потомков (в основном что угодно).
Однако по соображениям производительности примитивам в Java или типам значений в C # был присвоен особый статус. Они не объект. Вы не можете сделать что-то вроде (в Java):
7.toString()
, хотя toString является методом для Object. Для того, чтобы связать этот узел с производительностью, были созданы эквивалентные объекты. AutoBoxing удаляет стандартный код необходимости помещать примитив в его класс-обертку и извлекать его снова, делая код более читабельным.
Разница между типами значений и объектами в C # более серая. См. здесь о том, как они отличаются.
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.