Spec-Zone .ru
спецификации, руководства, описания, API
|
Как любой программист Java знает, невозможно поместить int
(или другое примитивное значение) в набор. Наборы могут только содержать ссылки на объект, таким образом, необходимо упаковать примитивные значения в соответствующий класс обертки (который является Integer
в случае int
). Когда Вы вынимаете объект из набора, Вы добираетесь Integer
то, что Вы вставляете; если Вы нуждаетесь int
, следует распаковать Integer
использование intValue
метод. Вся эта упаковка и распаковывание является болью, и загромождает Ваш код. Автоупаковка и распаковывание функции автоматизируют процесс, устраняя боль и помеху.
Следующий пример иллюстрирует автоупаковку и распаковывание, наряду с обобщениями и циклом foreach. В простых десяти строки кода это вычисляет и печатает расположенную в алфавитном порядке таблицу частот слов, появляющихся на командной строке.
import java.util.*; // Prints a frequency table of the words on the command line public class Frequency { public static void main(String[] args) { Map<String, Integer> m = new TreeMap<String, Integer>(); for (String word : args) { Integer freq = m.get(word); m.put(word, (freq == null ? 1 : freq + 1)); } System.out.println(m); } } java Frequency if it is to be it is up to me to do the watusi {be=1, do=1, if=1, is=2, it=2, me=1, the=1, to=3, up=1, watusi=1}
Программа сначала объявляет карту от String
к Integer
, соединение числа раз слово происходит на командной строке со словом. Затем это выполняет итерации по каждому слову на командной строке. Для каждого слова это ищет слово в карте. Затем это помещает пересмотренную запись для слова в карту. Строка, которая делает это (выделенный в зеленом) содержит и автоупаковку и распаковывание. Чтобы вычислить новое значение, чтобы связаться со словом, сначала это смотрит на текущую стоимость (freq
). Если это - нуль, это - первое возникновение слова, таким образом, это помещает 1 в карту. Иначе, это добавляет 1 к числу предшествующих возникновений и помещает то значение в карту. Но конечно невозможно поместить int
в карту, и при этом невозможно добавить тот к Integer
. То, что действительно происходит, является этим: Чтобы добавить 1 к freq
, это автоматически распаковывается, приводя к выражению типа int
. Так как оба из альтернативных выражений в условном выражении имеют тип int
, так также условное выражение непосредственно. Чтобы поместить это int
значение в карту, это автоматически упаковывается в Integer
.
Результат всего этого волшебства состоит в том, что можно в значительной степени проигнорировать различие между int
и Integer
, с несколькими протестами. Integer
у выражения может быть a null
значение. Если Ваша программа попытается автораспаковать нуль, то она бросит a NullPointerException
. ==
оператор выполняет ссылочные сравнения идентификационных данных на Integer
выражения и сравнения равенства значения на int
выражения. Наконец, есть затраты производительности, связанные с упаковкой и распаковыванием, даже если это делается автоматически.
Вот является другой пример программы обладающей автоупаковкой и распаковыванием. Это - статическая фабрика, которая берет int
массив и возвраты a List
из Integer
поддержанный массивом. В простых десяти строки кода этот метод обеспечивает полное богатство List
интерфейс на int
массив. Все изменения к списку пишут через в массив и наоборот. Строки, которые используют автоупаковку или распаковывание, выделяются в зеленом:
// List adapter for primitive int array public static List<Integer> asList(final int[] a) { return new AbstractList<Integer>() { public Integer get(int i) { return a[i]; } // Throws NullPointerException if val == null public Integer set(int i, Integer val) { Integer oldVal = a[i]; a[i] = val; return oldVal; } public int size() { return a.length; } }; }
Производительность получающегося списка, вероятно, будет плоха, как это поля или распаковывает на каждом get
или set
работа. Это - много достаточно быстро для случайного использования, но это было бы безумие, чтобы использовать это в производительности критический внутренний цикл.
Так, когда следует использовать автоупаковку и распаковывание? Используйте их только, когда есть "несоответствие импеданса" между ссылочными типами и примитивами, например, когда необходимо поместить численные значения в набор. Не уместно использовать автоупаковку и распаковывание для научных вычислений, или другой чувствительный к производительности числовой код. Integer
не замена int
; автоупаковка и распаковывание размытости различие между типами примитивов и ссылочными типами, но они не устраняют это.