Навигация
Главная
Поиск
Форум
FAQ's
Ссылки
Карта сайта
Чат программистов

Статьи
-Delphi
-C/C++
-Turbo Pascal
-Assembler
-Java/JS
-PHP
-Perl
-DHTML
-Prolog
-GPSS
-Сайтостроительство
-CMS: PHP Fusion
-Инвестирование

Файлы
-Для программистов
-Компонеты для Delphi
-Исходники на Delphi
-Исходники на C/C++
-Книги по Delphi
-Книги по С/С++
-Книги по JAVA/JS
-Книги по Basic/VB/.NET
-Книги по PHP/MySQL
-Книги по Assembler
-PHP Fusion MOD'ы
-by Kest
Professional Download System
Реклама
Услуги

Автоматическое добавление статей на сайты на Wordpress, Joomla, DLE
Заказать продвижение сайта
Программа для рисования блок-схем
Инженерный калькулятор онлайн
Таблица сложения онлайн
Популярные статьи
OpenGL и Delphi... 65535
Форум на вашем ... 65535
21 ошибка прогр... 65535
HACK F.A.Q 65535
Бип из системно... 65535
Гостевая книга ... 65535
Invision Power ... 65535
Пример работы с... 65535
Содержание сайт... 65535
ТЕХНОЛОГИИ ДОСТ... 65535
Организация зап... 65535
Вызов хранимых ... 65535
Создание отчето... 65535
Имитационное мо... 65535
Программируемая... 65535
Эмулятор микроп... 65535
Подключение Mic... 65535
Создание потоко... 65535
Приложение «Про... 65535
Оператор выбора... 65535
Реклама
Сейчас на сайте
Гостей: 12
На сайте нет зарегистрированных пользователей

Пользователей: 13,370
новичок: dogoco6
Новости
Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ
Delphi, Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog, 3D MAX, Компас 3D
Заказать программу для Windows Mobile, Symbian

База данных - словарь терминов на Delphi + Пояснительная записка
База данных студентов на Delphi + Microsoft SQL Server
База данных студентов на Delphi (файл записей) + Блок схемы

Автоупаковка и автораспаковка
Изучение новых функциональных возможностей, включенных в последнюю версию Java 2 5.0, начнем с так долго ожидаемых всеми программистами на языке Java автоупаковки (autoboxing) и автораспаковки (auto-unboxing). Выбор этот сделан по трем причинам. Во-первых, автоупаковка/автораспаковка сильно упрощает и рационализирует исходный код, в котором требуется объектное представление базовых типов языка Java, таких как int или char. Поскольку такие ситуации часто встречаются в текстах программ на Java, выигрыш от применения средств автоупаковки/распаковки получат практически все, программирующие на этом языке. Во-вторых, автоупаковка/автораспаковка во многом способствует простоте и удобству применения другого нового средства — настройки типов (generics). Следовательно, понимание автоупаковки и автораспаковки понадобится для последующего изучения этого механизма. В-третьих, автоупаковка/распаковка плавно изменяет наши представления о взаимосвязи объектов и данных базовых типов. Эти изменения гораздо глубже, чем может показаться на первый взгляд из-за концептуальной простоты двух описываемых здесь новых функциональных возможностей. Их влияние ощущается во всем языке Java.
Автоупаковка и автораспаковка напрямую связаны с оболочками типов (type wrapper) языка Java и со способом вставки значений в экземпляры таких оболочек и извлечения значений из них. По этой причине мы начнем с краткого обзора оболочек типов и процесса упаковки и распаковки значений для них.
Обзор оболочек типов и упаковки значений
Как вам известно, в языке Java используются базовые типы (также называемые простыми), такие как int или double, для хранения элементарных данных типов, поддерживаемых языком. Для хранения таких данных из-за более высокой производительности применяются базовые типы, а не объекты. В этом случае использование объектов добавляет неприемлемые издержки даже к простейшей вычислительной операции. Таким образом, базовые типы не являются частью иерархии объектов и не наследуют класс Object.
Несмотря на выигрыш в производительности, предлагаемый базовыми типами, возникают ситуации, требующие обязательного объектного представления. Например, Вы не можете передать в метод переменную базового типа как параметр по ссылке. Кроме того, много стандартных cтруктур данных, реализованных в языке Java, оперирует объектами, и, следовательно, Вы не можете использовать эти структуры для хранения данных базовых типов. Для подобных (и других) случаев Java предоставляет оболочки типов, представляющие собой классы, которые инкапсулируют данные простого типа в объект. Далее перечислены классы оболочки типов.
Boolean Byte Character Double
Float Long Integer Short
Значение базового типа инкапсулируется в оболочку в момент конструирования объекта. Упакованное таким образом значение можно получить обратно с помощью вызова одного из методов, определенных в оболочке. Например, все оболочки числовых типов предлагают следующие методы:
byte byteValue() double doubleValue() float floatValue()
int intValue() long longValue() short shortValue()
Каждый метод возвращает значение заданного базового типа. Например, объект типа Long может вернуть значение одного из встроенных числовых типов, включая short, double или long.
Процесс инкапсуляции значения в объект называется упаковкой (boxing). До появления Java 2 версии 5.0 вся упаковка выполнялась программистом вручную, с помощью создания экземпляра оболочки с нужным значением. В приведенной далее строке кода значение 100 упаковывается вручную в объект типа Integer:
Integer iOb = new Integer(l00);
В приведенном примере новый объект типа Integer со значением 100 создается явно и ссылка на него присваивается переменной iOb.
Процесс извлечения значения из оболочки типа называется распаковкой (unboxing). И снова, до появления Java 2 версии 5.0 вся распаковка выполнялась вручную с помощью вызова метода оболочки для получения значения из объекта.
В следующей строке кода значение из объекта iOb вручную распаковывается в переменную типа int:
int i = iOb.intValue();
В данном случае метод intValue() возвращает значение типа int из объекта iOb. Как объяснялось ранее, есть и другие методы, позволяющие извлечь из объекта значение другого числового типа, такого как byte, short, long, double или float. Например, для получения значения типа long из объекта iOb Вам следует вызвать метод iOb.longValue(). Таким образом, можно распаковать значение в переменную простого типа, отличающегося от типа оболочки.
Начиная с первоначальной версии языка Java, для упаковки и распаковки вручную выполнялась одна и та же базовая процедура, приведенная в предыдущих примерах. Хотя такой способ упаковки и распаковки работает, он утомителен и подвержен ошибкам, так как требует от программиста вручную создавать подходящий объект для упаковки значения и при необходимости его распаковки явно задавать переменную соответствующего базового типа. К счастью Java 2, v5.0 коренным образом модернизирует эти важнейшие процедуры, вводя средства автоупаковки/распаковки.
Основы автоупаковки/распаковки
Автоупаковка (autoboxing) — это процесс автоматической инкапсуляции данных простого типа, такого как int или double, в эквивалентную ему оболочку типа, как только понадобится объект этого типа. При этом нет необходимости в явном создании объекта нужного типа. Автораспаковка (auto-unboxing) — это процесс автоматического извлечения из упакованного объекта значения, когда оно потребуется. Вызовы методов, таких как intValue() и doubleValue(), становятся ненужными.
Добавление средств автоупаковки/автораспаковки значительно упрощает кодирование ряда алгоритмов, исключая утомительные упаковку и распаковку, выполняемые вручную. Кроме того, эти новые средства программирования позволяют избежать ошибок за счет устранения возможности распаковки вручную неверного типа из оболочки. Автоупаковка также облегчает использование настраиваемых типов (generics) и запоминание данных базовых типов в коллекциях.
Благодаря автоупаковке исчезает необходимость в создании вручную объекта для инкапсуляции значения простого типа. Вам нужно только присвоить это значение указателю на объект типа-оболочки. Язык Java автоматически создаст для вас этот объект. В следующей строке приведен пример современного способа конструирования объекта типа Integer, хранящего значение 100:
Integer iOb = 100; // автоматически упаковывает значение типа int
Обратите внимание на то, что никакого объекта не создается явно, с помощью операции new. Язык Java выполнит это автоматически.
Для автораспаковки объекта просто присвойте ссылку на него переменной соответствующего базового типа. Например, для распаковки объекта iOb можно использовать следующую строку кода:
int i = iOb; // автораспаковка
Все детали выполнит для вас язык Java.
В листинге 2.1 приведена короткая программа, вобравшая в себя все приведенные ранее фрагменты и демонстрирующая основы механизма автоупаковки/распаковки,
Листинг 2.1. Демонстрация применения автоупаковки/распаковки

// Demonstrate autoboxing/unboxing.
class AutoBox {

public static void main(String args[]) {
Integer iOb = 100; ; // автоупаковка значения типа int
int i = iOb; // автораспаковка
System.out.println(i + " " + iOb); // отображает на экране: 100 100

}
}



Обратите внимание еще раз на то, что не нужно явно создавать объект типа Integer для упаковки значения 100 и нет необходимости вызывать метод intValue() для распаковки этого значения.
Автоупаковка и методы
Помимо простых случаев присваивания, автоупаковка выполняется автоматически каждый раз, когда данные базового типа должны быть преобразованы в объект, а автораспаковка — при необходимости преобразования объекта в значение базового типа. Следовательно, автоупаковка/распаковка может происходить, когда аргумент передается в метод или когда значение возвращается методом. Рассмотрим пример, приведенный в листинге 2.2.
Листинг 2.2. Автоупаковка/распаковка параметров метода и возвращаемых им значений
// Autoboxing/unboxing takes place with
// method parameters and return values.

class AutoBox2 {
// Принимает параметр типа Integer и возвращает
// значение типа int;

static int m(Integer v) {
return v ; // auto-unbox to int
}

public static void main(String args[]) {
// Передает значение int в метод m() и присваивает возвращаемое
// значение объекту типа Integer. Здесь аргумент 100
// автоупаковывается в объект типа Integer. Возвращаемое значение
// также автоупаковывается в тип Integer.

Integer iOb = m(100);

System.out.println(iOb);
}
}



Программа листинга 2.2 отображает следующий ожидаемый результат:
100
В приведенной программе метод задает параметр типа Integer и возвращает результат типа int. В теле main() методу m() передается значение 100. Поскольку ожидает объект типа Integer, передаваемое значение автоматически упаковывается. Далее метод то возвращает эквивалент своего аргумента, но простого типа int. Это приводит к автоматической распаковке в переменную v. Далее в методе main() объекту iOb присваивается это значение типа int, что вызывает его автоупаковку. Главное преимущество заключается в том, что все преобразования выполняются автоматически.
Автоупаковка/распаковка в выражениях
Вообще, автоупаковка/распаковка происходит всегда, когда требуется преобразование в объект или из объекта. Это применимо и к выражениям. В них числовой объект автоматически распаковывается. Результат выражения повторно упаковывается, если это необходимо. Рассмотрим программу, приведенную в листинге 2.3.
Листинг 2.3. Автоупаковка/распаковка внутри выражений

class AutoBox3 {
public static void main(String args[]) {

Integer iOb, iOb2;
int i;

iOb = 100;
System.out.println("Original value of iOb: " + iOb);

// Далее автоматически распаковывается объект iOb,
// выполняется операция инкремента, затем результат
// повторно упаковывается в объект iOb.

++iOb;
System.out.println("After ++iOb: " + iOb);

// Здесь iOb распаковывается, выражение
// вычисляется и результат повторно упаковывается
// и присваивается iOb2.

iOb2 = iOb + (iOb / 3);
System.out.println("iOb2 after expression: " + iOb2);
// To же самое выражение вычисляется, но результат
// повторно не упаковывается.

i = iOb + (iOb / 3);
System.out.println("i after expression: " + i);

}
}




Далее приведен вывод программы, отображающий результаты ее работы.
Original value of iOb: 100
After ++iOb: 101
iOb2 after expression: 134
i after expression: 134
Обратите особое внимание на следующую строку программы из листинга 2.3:
++iOb;
Она вызывает увеличение на единицу значения, упакованного в объекте iOb. Это действие выполняется следующим образом: объект iOb распаковывается, значение увеличивается, и результат повторно упаковывается.
Автораспаковка позволяет смешивать в выражении числовые объекты разных типов. После того как значения распакованы, к ним применимы стандартные преобразования типов и переходы от одного к другому. Например, приведенная в листинге 2.4 программа вполне корректна.
Листинг 2.4. Обработка числовых объектов разных типов в одном выражении

class AutoBox4 {
public static void main(String args[]) {

Integer iOb = 100;
Double dOb = 98.6;

dOb = dOb + iOb;
System.out.println("dOb after expression: " + dOb);
}
}



Далее приведен результат работы программы из листинга 2.4.
iOb after expression: 198.6
Как видите, и объект dOb типа Double, и объект iOb типа Integer участвовали в сложении, а результат был повторно упакован и сохранен в объекте dOb.
Благодаря автораспаковке Вы можете использовать целочисленный объект для управления оператором 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.
Приведенные примеры программ показывают, что наличие автоупаковки/распаковки делает использование числовых объектов в выражении легким и интуитивно понятным. В прошлом в этот код пришлось бы вставлять вызовы методов, подобных intValue().
Автоупаковка/распаковка логических и символьных значений
Кроме оболочек для числовых типов язык Java также предоставляет оболочки для данных типов boolean и char. Они называются Boolean и Character соответственно. К ним также применимы автоупаковка/распаковка. Рассмотрим программу, приведенную в листинге 2.5.

Листинг 2.5. Автоупаковка/распаковка типов Boolean и Character

class AutoBox5 {
public static void main(String args[]) {
// Автоупаковка/распаковка логических переменных.
Boolean b = true;

// Далее объект b автоматически распаковывается, когда используется
// в условном выражении оператора, такого как if.
if(b) System.out.println("b is true");
// Автоупаковка/распаковка символьных переменных.

Character ch = 'x'; // box a char
char ch2 = ch; // unbox a char

System.out.println("ch2 is " + ch2);
}
}



Далее приведен вывод программы из листинга 2.5, отображающий результаты ее работы:
b is true
ch2 is x
Наиболее важной в программе из листинга 2.5 является автораспаковка объекта b внутри условного выражения в операторе if. Как вы должны помнить, условное выражение, управляющее выполнением оператора if, следует вычислять как значение типа boolean. Благодаря наличию автораспаковки логическое значение, содержащееся в объекте b, автоматически распаковывается при вычислении условного выражения. Таким образом, с появлением Java 2 v5.0 стало возможным использование объекта типа Boolean для управления оператором if.
Более того, теперь объект типа Boolean можно применять для управления любыми операторами цикла языка Java. Когда объект типа Boolean используется как условное выражение в циклах while, for, do/while, он автоматически распаковывается в эквивалент простого типа boolean. Например, приведенный далее фрагмент теперь абсолютно корректен.
Boolean b;
//
while (b) { //

Помощь автоупаковки/распаковки в предупреждении ошибок
Кроме удобства, которое предоставляет механизм автоупаковки/распаковки, он может помочь в предупреждении ошибок. Рассмотрим программу, приведенную в листинге 2.6.
Листинг 2.6. Ошибка, возникшая при распаковке вручную
class UnboxingError {
public static void main(String args[]) {

Integer iOb = 1000;
// автоматически упаковывает значение 1000
int i = iOb.byteValue();// вручную распаковывается как тип byte !!!
System.out.println(i);// не отображает значение 1000
}
}




Программа из листинга 2.6 отображает число -24 вместо ожидаемого значения 1000! Причина заключается в том, что значение, хранящееся в объекте iOb, распаковывается вручную с помощью вызова метода byteValue() который приводит к усечению этого значения, равного 1000. В результате переменной i присваивается число -24, так называемый "мусор". Автораспаковка препятствует возникновению ошибок этого типа, потому что она преобразует значение, хранящееся в iOb, в величину базового типа, сопоставимого с типом int.
Вообще говоря, поскольку автоупаковка всегда создает правильный объект, а автораспаковка всегда извлекает надлежащее значение, не возникает ситуаций для формирования неверного типа объекта или значения. В редких случаях, когда Вам нужен тип, отличающийся от созданного автоматическим процессом, Вы и сейчас можете упаковывать и распаковывать значения вручную так, как делали это раньше. Конечно, при этом теряются преимущества автоупаковки/распаковки. Как правило, во вновь разрабатываемом коде должны применяться эти механизмы, так как они соответствуют современному стилю программирования на языке Java.
Предостережения
Теперь, когда в язык Java включены средства автоупаковки/распаковки, может появиться желание использовать только числовые объекты типа Integer или Double, полностью отказавшись от данных простых типов. Например, благодаря наличию автоупаковки/распаковки теперь можно написать код, подобный приведенному далее.
//Пример плохого использования автоупаковки/распаковки Double a,b,c;
а = 10.0;
b = 4.0;
с = Math.sqrt(a*a + b*b);
System.out.println("Hypotenuse is " + c);



В приведенном примере объекты типа Double содержат значения, которые используются для вычисления гипотенузы прямоугольного треугольника. Хотя этот код технически корректен и будет выполняться правильно, он служит образцом очень плохого применения автоупаковки/распаковки. Гораздо эффективнее использовать данные простого типа double для подобных вычислений, т. к. каждая автоупаковка и автораспаковка вносят дополнительные затраты, которых лишены вычисления с применением базовых типов данных.
Вообще говоря, следует ограничить использование оболочек типов только теми случаями, для которых требуется объектное представление данных простых типов. Автоупаковка/автораспаковка включены в язык таким образом, чтобы не ограничивать применение простых типов данных.
Опубликовал Kest January 12 2009 21:39:27 · 0 Комментариев · 9938 Прочтений · Для печати

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •


Комментарии
Нет комментариев.
Добавить комментарий
Имя:



smiley smiley smiley smiley smiley smiley smiley smiley smiley
Запретить смайлики в комментариях

Введите проверочный код:* =
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Поделиться ссылкой
Фолловь меня в Твиттере! • Смотрите канал о путешествияхКак приготовить мидии в тайланде?
Загрузки
Новые загрузки
iChat v.7.0 Final...
iComm v.6.1 - выв...
Visual Studio 200...
CodeGear RAD Stud...
Шаблон для новост...

Случайные загрузки
Цветной Grid
ComboBox97
Gold Submitter II...
Billenium Effects...
Delphi 2005 Секре...
PHP5. Профессиона...
Игра PackMan
Еext Editor
Формирование отче...
Использование Lis...
IpEditAdress
Игра в крестики н...
Zoom [Исходник на...
Visual Studio 200...
Определние размер...
Print Grid
Программа предназ...
Х. М. Дейтел, П. ...
FreeNet
PHP 5 для "чайников"

Топ загрузок
Приложение Клие... 100774
Delphi 7 Enterp... 97836
Converter AMR<-... 20268
GPSS World Stud... 17014
Borland C++Buil... 14191
Borland Delphi ... 10291
Turbo Pascal fo... 7374
Калькулятор [Ис... 5984
Visual Studio 2... 5207
Microsoft SQL S... 3661
Случайные статьи
Программа формиров...
Вариант For-Each ц...
Требования голосов...
С чего начать
PHP и DNS. Проверк...
Постоянная интеграция
Задание на моделир...
Особенности агреги...
Непосредственные в...
Модуль System
Программа реализую...
Получение объектов...
Заключение
Разделение памяти ...
Прожигатетели врем...
Модуль Legacy
Анонимность пользо...
Подвесной светильн...
Зачем нужно исчисл...
Поле "Скрытая" при...
Чем занимаются СРО?
Решения к главе 15
Эталонная модель п...
Режим “Макро” в фо...
Инерция тепла
Статистика



Друзья сайта
Программы, игры


Полезно
В какую объединенную сеть входит классовая сеть? Суммирование маршрутов Занимают ли таблицы память маршрутизатора?