Чтение онлайн

на главную

Жанры

Java: руководство для начинающих
Шрифт:

В данной программе целочисленное значение 100 упаковывается в объект типа Integer, на который ссылается переменная iOb. Для извлечения упакованного числового значения вызывается метод intValue . Полученное значение сохраняется в переменной i. А в конце программы на экран выводятся значения переменных i и iOb, каждое из которых равно 100.

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

Автоупаковка — это процесс автоматической инкапсуляции (упаковки) простого типа данных в объекте

оболочки соответствующего типа всякий раз, когда в этом возникает потребность, причем создавать такой объект явным образом не нужно. Автораспаковка — это процесс автоматического извлечения (распаковки) из объекта оболочки упакованного в нем значения соответствующего типа всякий раз, когда в этом возникает потребность. Благодаря автораспаковке отпадает необходимость в вызове таких методов, как intValue и doubleValue .

Поддержка автоупаковки и автораспаковки существенно упрощает реализацию целого ряда алгоритмов, так как в этом случае все рутинные операции по упаковке и распаковке значений простых типов берет на себя исполняющая система Java, что позволяет уменьшить вероятность возникновения программных ошибок. Автоупаковка освобождает программирующего на Java от необходимости создавать вручную объекты для заключения в них простых типов данных. Достаточно присвоить упаковываемое значение переменной ссылки на объект оболочки соответствующего типа, а нужный объект будет автоматически создан исполняющей системой Java. Ниже приведен пример создания объекта типа Integer, в который автоматически упаковывается целочисленное значение 100. Integer iOb = 100; // Автоупаковка целочисленного значения

Обратите внимание на то, что в данном примере отсутствует оператор new, конструирующий объект явным образом. Создание объекта происходит автоматически.

Для распаковки значения из объекта достаточно присвоить переменной простого типа ссылку на этот объект. Например, для распаковки значения, упакованного в объекте iOb, нужно лишь ввести в код следующую единственная строку: int i = iOb; // Автораспаковка

А все остальное возьмет на себя исполняющая система Java. Ниже приведен пример программы, демонстрирующий автоупаковку и автораспаковку. // Применение автоупаковки и автораспаковки, class AutoBox { public static void main(String args[]) { // Автоупаковка и автораспаковка значения 100. Integer iOb = 100; int i = iOb; System.out.println(i + " " + iOb); // displays 100 100 } } Автоупаковка и методы

Автоупаковка и автораспаковка происходят не только в простых операциях присваивания, но и в тех случаях, когда простой тип требуется преобразовать в объект, и наоборот. Следовательно, автоупаковка и автораспаковка могут происходить при передаче аргумента методу и при возврате значения последним. Рассмотрим в качестве примера следующую программу: // Автоупаковка и автораспаковка при передаче // параметров и возврате значений из методов. class AutoBox2 { // Этот метод принимает параметр типа Integer. static void m(Integer v) { System.out.println("m received " + v); } // Этот метод возвращает значение типа int. static int m2 { return 10; } // Этот метод возвращает значение типа Integer. static Integer m3 { return 99; // Автоупаковка значения 99 в объект типа Integer. } public static void main(String args[]) { // Передача методу m значения типа int. // Метод m принимает параметр типа Integer, // поэтому значение int автоматически упаковывается, m(199); // Здесь объект ЮЬ получает значение типа int, возвращаемое // методом т2. Это значение автоматически упаковывается, // чтобы его можно было присвоить объекту iOb. Integer iOb = m2; System.out.println("Return value from m2 is " + iOb); // А здесь метод m3 возвращает значение типа Integer, которое // автоматически распаковывается и преобразуется в тип int. int i = m3; System.out.println("Return value from m3 is " + i); // Здесь методу Math.sqrt в качестве параметра передается // объект iOb, который автоматически распаковывается, а его // значение продвигается к типу double, требующемуся для // выполнения данного метода. iOb = 100; System.out.println("Square root of iOb is " + Math.sqrt(iOb)); } }

Результат выполнения данной программы выглядит так: m received 199 Return value from m2 is 10 Return value from m3 is 99 Square root of iOb is 10.0

В объявлении метода m указывается, что ему должен передаваться параметр типа Integer. В методе main целочисленное значение 199 передается методу m в качестве параметра. В итоге происходит автоупаковка этого целочисленного значения. Далее в программе

вызывается метод m2 , возвращающий целочисленное значения 10. Это значение присваивается переменной ссылки на объект iOb в методе main . А поскольку объект iOb относится к типу Integer, то целочисленное значение, возвращаемое методом m2 , автоматически упаковывается. Затем в методе main вызывается метод m3 . Он возвращает объект типа Integer, который посредством автораспаковки преобразуется в тип int. И наконец, в методе main вызывается метод Math. sqrt , которому в качестве аргумента передается объект iOb. В данном случае происходит автораспаковка данного объекта, а его значение продвигается к типу double, поскольку параметр именно этого типа должен быть передан методу Math. sqrt . Автоупаковка и автораспаковка в выражениях

Автоупаковка и автораспаковка выполняются всякий раз, когда объект необходимо преобразовать в простой тип, а простой тип — в объект. Так, автораспаковка производится при вычислении выражений, и если требуется, то результат вычисления упаковывается. Рассмотрим в качестве примера приведенную ниже программу. // Автоупаковка и автораспаковка в выражениях. class AutoBox3 { public static void main(String args[]) { Integer iOb, i0b2; int i; iOb = 99; System.out.println("Original value of iOb: " + iOb); // В следующем выражении объект iOb автоматически // распаковывается, производятся вычисления, а результат // снова упаковывается в объект iOb. ++iOb; System.out.println("After ++iOb: и + iOb); // В последующем выражении производится автораспаковка // объекта iOb, к полученному значению прибавляется число 10, // а результат снова упаковывается в объект iOb. iOb += 10; System.out .println ("After iOb +=? 10: " + iOb) ; //И в следующем выражении объект iOb автоматически // распаковывается, выполняются вычисления, а результат // снова упаковывается в объект iOb. iOb2 = iOb + (iOb / 3); System.out.println("iOb2 after expression: " + iOb2); // А в этом случае вычисляется то же самое выражение, // но повторная упаковка не производится, i = iOb + (iOb / 3); System.out.println("i after expression: " + i); } }

Выполнение этой программы дает следующий результат: Original value of iOb: 99 After ++iOb: 100 After iOb += 10: 110 iOb2 after expression: 146 i after expression: 146

В данной программе особое внимание обратите на следующую строку кода: ++iOb;

В ней значение объекта iOb должно быть увеличено на единицу. Происходит это следующим образом: объект iOb распаковывается, полученное значение инкрементируется, а результат снова упаковывается в объект iOb.

Благодаря автораспаковке объекты оболочек целочисленных типов, например Integer, можно использовать в операторах switch. В качестве примера рассмотрим следующий фрагмент кода: Integer iOb = 2; switch(iOb) { case 1: System.out.println("one") ; break; case 2: System.out.println("two"); break; default: System.out.println("error") ; }

При вычислении выражения в операторе switch объект iOb распаковывается и последующей обработке подвергается значение типа int, упакованное в этом объекте.

Как следует из приведенных выше примеров, выражения, в которых применяются объекты оболочек простых типов, становятся интуитивно понятными благодаря автоупаковке и автораспаковке. До появления версии JDK 5 для достижения аналогичного результата в программе приходилось прибегать к приведению типов и вызовам специальных методов вроде intValue . Предупреждение относительно автоупаковки и автораспаковки

Теперь, когда автоупаковка и автораспаковка предельно упрощают обращение с оболочками простых типов, может возникнуть сильное искушение пользоваться вместо простых типов только их оболочками, например Integer или Double. Так, например, автоупаковка и автораспаковка позволяют создавать код, аналогичный приведенному ниже. // Неоправданное использование автоупаковки и автораспаковки. Double а, Ь, с; а = 10.2; b = 11.4; с = 9.8; Double avg = (a + b + c)./3;

В данном примере в объектах типа Double хранятся три значения, используемые для вычисления арифметического среднего, а полученный результат присваивается другому объекту типа Double. И хотя такой код формально считается корректным, а следовательно, будет выполняться правильно, тем не менее, автоупаковка и автораспаковка применяются в нем совершенно не оправданно. Ведь подобный код значительно менее эффективен аналогичного кода, написанного только с использованием переменных типа double. А каждая распаковка и упаковка связана с издержками, которые простые типы не налагают на вычислительные ресурсы.

Поделиться:
Популярные книги

Камень. Книга пятая

Минин Станислав
5. Камень
Фантастика:
боевая фантастика
6.43
рейтинг книги
Камень. Книга пятая

Черный маг императора

Герда Александр
1. Черный маг императора
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Черный маг императора

Кодекс Крови. Книга VI

Борзых М.
6. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга VI

Отверженный. Дилогия

Опсокополос Алексис
Отверженный
Фантастика:
фэнтези
7.51
рейтинг книги
Отверженный. Дилогия

Неудержимый. Книга XIII

Боярский Андрей
13. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга XIII

Черный Маг Императора 6

Герда Александр
6. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
7.00
рейтинг книги
Черный Маг Императора 6

Начальник милиции. Книга 3

Дамиров Рафаэль
3. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции. Книга 3

На границе империй. Том 9. Часть 2

INDIGO
15. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 2

Лорд Системы 13

Токсик Саша
13. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Лорд Системы 13

На границе империй. Том 9. Часть 4

INDIGO
17. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 4

Вторая невеста Драконьего Лорда. Дилогия

Огненная Любовь
Вторая невеста Драконьего Лорда
Любовные романы:
любовно-фантастические романы
5.60
рейтинг книги
Вторая невеста Драконьего Лорда. Дилогия

Неудержимый. Книга X

Боярский Андрей
10. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга X

Гарем вне закона 18+

Тесленок Кирилл Геннадьевич
1. Гарем вне закона
Фантастика:
фэнтези
юмористическая фантастика
6.73
рейтинг книги
Гарем вне закона 18+

В зоне особого внимания

Иванов Дмитрий
12. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
В зоне особого внимания