Главная страница

Java. Полное руководство. 8-е издание. С. Н. Тригуб Перевод с английского и редакция


Скачать 25.04 Mb.
НазваниеС. Н. Тригуб Перевод с английского и редакция
АнкорJava. Полное руководство. 8-е издание.pdf
Дата28.02.2017
Размер25.04 Mb.
Формат файлаpdf
Имя файлаJava. Полное руководство. 8-е издание.pdf
ТипДокументы
#3236
страница22 из 90
1   ...   18   19   20   21   22   23   24   25   ...   90
s witch(result)
{
case Нет
break;
case Да
break;
case Возможно
break;
case Позднее
break;
case Вскоре
break;
case Никогда
break;
}
public static void main(String a r g s [])
Question q = new Question();
answer(q.ask()
answer(q.ask()
answer(q.ask() Оболочки типов

Как вызнаете, в языке Java для хранения базовых типов данных, поддерживаемых языком, используются элементарные типы (также называемые простыми типами, такие как i n t или d o u b le . Элементарные типы, в отличие от объектов, используются для таких значений из соображений производительности

2 9 8 Часть I. Язык Применение объектов для этих значений приводит к нежелательным накладным расходам, даже в случае простейших вычислений. Поэтому элементарные типы не являются частью иерархии объектов и не наследуются от класса
Ob j Несмотря на то что элементарные типы обеспечивают выигрыш производительности, бывают случаи, когда вам может понадобиться объектное представление. Например, вы не можете передать в метод элементарный тип по ссылке. Кроме того, многие стандартные структуры данных, реализованные в языке Java, оперируют объектами, а это означает, что вы не можете применять эти структуры данных для сохранения элементарных типов. Чтобы справиться с такими (и подобными) ситуациями, язык Java предлагает оболочки шипов, которые представляют собой классы, заключающие элементарный тип в объект. Классы-оболочки типов детально описаны в части II, но поскольку они имеют непосредственное отношение к автоупаковке Java, кратко рассмотрим их здесь.
Оболочки типов—это
Double, Float, Long, Integer, Short, Byte, Character и
Boolean. Эти классы предоставляют широкий диапазон методов, позволяющий в полной мере интегрировать элементарные типы в иерархию объектных типов
Java. Каждый из них кратко рассматривается далее.
Класс C h a r a c t e Этот класс является оболочкой вокруг типа char. Конструктор
Character
() выглядит следующим образом

символ)
Здесь символ указывает символ, который будет помещен в оболочку при создании объекта класса Чтобы получить значение типа char, содержащееся в объекте класса
Character, вызовите метод charValue ()
, показанный ниже Он возвращает инкапсулированный символ.
Класс B o o le a Это — оболочка вокруг значений типа boolean. В ней определены следующие конструкторы
логическоеЗначение)
Boolean(String
логическаяСтрока)
В первой версии
логическоеЗначение должно быть либо true, либо false. Во второй версии, если
логическаяСтрока содержит строку "true" в верхнем или нижнем регистре, новый объект класса
Boolean будет содержать значение true. В противном случае он будет содержать значение Чтобы получить значение типа boolean из объекта класса
Boolean, используйте метод booleanValue ()
, показанный ниже,
boolean Он возвращает эквивалент типа boolean вызывающего объекта.
Оболочки числовых типов
До сих пор наиболее часто используемыми оболочками типов являются те, что представляют числовые значения. Это
Byte, Short, Integer, Long, Float и
Double. Все оболочки числовых типов наследуют абстрактный класс
Number.
Глава 12. Перечисления, автоупаковка и аннотации (метаданные)
2 9 Этот класс объявляет методы, которые возвращают значение объекта в каждом из числовых форматов. Вот эти методы byteValueO
double doubleValue()
float floatValueO
int intValue()
long longValue()
short Например, метод doubleValue
() возвращает значение объекта как тип dou­
ble, метод f loatValue (
) — как тип float и т.д. Эти методы реализованы каждой из оболочек числовых типов.
Все оболочки числовых типов определяют конструкторы, которые позволяют создавать объекты из заданного значения или строкового представления этого значения. Например, вот как выглядят конструкторы для класса
Integer.
Integer(int число
строка)
Если строка не содержит числового значения, то передается исключение Все оболочки типов переопределяют метод toString ()
. Этот метод возвращает читабельную для человека форму значения, содержащегося в оболочке. Например, это позволяет выводить значение, передавая объект оболочки типа методу println
() без необходимости преобразования его в элементарный тип. В следующей программе показано, как использовать оболочку числового типа для инкапсуляции значения и последующего его извлечения Демонстрация оболочки типа
class Wrap {
public static void main(String a r g s []) {
Integer iOb = new Integer(100);
int i = iO b .intValue();
System.out.println(i + " " + iOb); // отображает 100 Эта программа помещает целое значение 100 внутрь объекта класса
Integer по имени iOb. Затем она получает значение за счет вызова метода intValue
() и помещает результат в переменную Процесс инкапсуляции значения в объект называется упаковкой (boxing). То есть следующая строка программы упаковывает значение 100 в объект класса
Integer.
Integer iOb = new Процесс извлечения значения из оболочки типа называется распаковкой
(unboxing). Например, приведенная строка программы распаковывает значение объекта iOb.
int i = О Та же общая процедура, что используется в предыдущей программе для упаковки и распаковки значений, применялась ив исходной версии языка Java. Однако в версию Java J2SE 5 были внесены фундаментальные усовершенствования за счет добавления автоматической упаковки, описанной ниже

3 0 Часть I. Язык Java
Автоупаковка
Начиная св язык Java добавлены два важных средства авшоупаковка
(autoboxing) и автораспаковка (autounboxing). Автоупаковка — это процесс, в результате которого элементарный тип автоматически инкапсулируется (упаковывается) в эквивалентную ему оболочку типа всякий раз, когда требуется объект этого типа. Нет необходимости явного создания объекта. Автораспаковка — это процесс автоматического извлечения значения упакованного объекта (распаковка) из оболочки типа, когда нужно получить его значение. Нет необходимости вызывать методы вроде intValue (
) или doubleValue (Добавление автоматической упаковки и распаковки значительно упрощает реализацию некоторых алгоритмов, исключая необходимость в ручной упаковке и распаковке значений. Это также помогает предотвратить ошибки. Более того, это очень важно для средства обобщения классов и алгоритмов, которые оперируют только объектами. И наконец, автоупаковка существенно облегчает работу с инфраструктурой коллекций Collection Framework, описанной в части С применением автоупаковки больше нет необходимости в ручном создании объектов для оболочки элементарных типов. Вам нужно только присвоить значение ссылке оболочки типов. Язык Java автоматически создаст эти объекты для вас. Например, вот современный способ создания объекта класса
Integer, который содержит значение 100.
Integer iOb = 100; // автоупаковка Обратите внимание объект не создается явно оператором new. Язык Java делает это за вас автоматически.
Чтобы распаковать объект, просто присваивайте ссылку на объект переменной элементарного типа. Например, чтобы распаковать объект iOb, следует использовать следующую строку i = iOb; // автораспаковка

Java справляется с деталями за вас.
Вот предыдущая программа, переписанная для использования автоупаковки и автораспаковки.
// Демонстрация автоупаковки/автораспаковки,
class AutoBox {
public static void main(String a r g s []) {
Integer iOb = 100; // автоупаковка int
int i = iOb;
// автораспаковка
System.out.pri n t l n (i + " " + iOb);
// отображает 100 100
}
}
Автоупаковка и методы
В дополнение к простым случаям присвоения, автоупаковка происходит автоматически всякий раз, когда элементарный тип должен быть преобразован в объект. Автораспаковка происходит всякий раз, когда объект должен быть преобразован в элементарный тип. Таким образом, автоупаковка и автораспаковка могут
Глава 12. Перечисления, автоупаковка и аннотации (метаданные)
3 0 осуществляться, когда аргумент передается методу либо когда значение возвращается из метода. Рассмотрим пример Автоупаковка/автораспаковка происходит с методами параметров и возвращаемыми значениями AutoBox2 {
// принять параметр Integer и вернуть значение int;
static int m(Integer v) {
return v ;
// автораспаковка int
}
public static void main(String a r g s []) {
// Передача int методу m() и присвоение возвращаемого значения
// объекту Integer. Здесь аргумент 100 автоматически
// упаковывается в Integer. Возвращаемое значение также
// упаковывается в Integer.
Integer iOb = Эта программа отображает следующий результат.
100
Обратите внимание на то, что в этой программе метод ш () задает параметр класса I n t e g e r и возвращает результат типа i n t . Внутри метода m a i n ( ) методу ш) передается значение 100. Поскольку метод ш) ожидает объект класса
I n t e g e r , это значение автоматически упаковывается. Затем метод ш () возвращает эквивалент аргумента типа i n t . Это заставляет автоматически упаковаться в переменную v. Далее это значение типа i n t присваивается объекту iOb в методе m a i n (), что вызывает автоматическую упаковку результата типа i n t .
Автоупаковка и распаковка в выражениях Вообще, автоупаковка и распаковка происходят всякий раз, когда требуется преобразование в объект или из объекта. Это касается выражений. Внутри выражения числовой объект автоматически распаковывается. Выходной результат выражения при необходимости упаковывается заново. Например, рассмотрим следующую программу Автоупаковка/распаковка происходят в выражениях AutoBox3 {
public static void main(String a r g s []) {
Integer iOb, iOb2;
int i ;
iOb = Исходное значение iOb: " + iOb);
// Следующее автоматически распаковывает iOb,
// выполняет его приращение, затем повторно
// упаковывает результат обратно в После ++iOb: " + iOb);

3 0 Часть I. Язык Java
// Здесь iOb распаковано, выражение вычисляется а результат снова упаковывается и
// присваивается Ю Ь 2 Ю Ь 2 = iOb + (iOb / 3);
System.out.println("iOb2 после выражения " + iOb2);
// Вычисляется тоже самое выражение / но результат не упаковывается
i = iOb + (iOb / 3);
System.out.println("i после выражения " + Вывод показан ниже.
Исходное значение iOb: 100 После ++iOb: 101

iOb2 после выражения 134
i после выражения Обратите особое внимание наследующую строку программы.
++iOb;
Она увеличивает назначение объекта iOb. Это работает следующим образом объект iOb распаковывается, значение увеличивается и результат упаковывается вновь.
Автоматическая распаковка также позволяет смешивать разные типы числовых объектов водном выражении. Как только значение распаковано, применяются стандартные правила повышения типов и преобразования. Например, следующая программа абсолютно корректна AutoBox4 {

public static void main(String a r g s []) {
Integer iOb = 100;
Double dOb = 98.6;
dOb = dOb + iOb;
System.out.println("dOb после выражения " + dO b ) Результат показан ниже после выражения Как видите, оба объекта — и dOb класса
Double, и iOb класса
Integer
— участвуют в сложении, и результат повторно упаковывается и сохраняется в объекте Благодаря автоупаковке, можно применять целочисленные объекты для управления оператором switch. Например, рассмотрим следующий фрагмент кода iOb = 2;

switch(iOb) {
case 1: один
break;
case 2: System.out.p r два
break;
default:
ошибка
Глава 12. Перечисления, автоупаковка и аннотации (метаданные)
3 0 Когда вычисляется выражение switch, объект iOb распаковывается и возвращается его значение типа Как показывают примеры программ, благодаря автоупаковке и распаковке, применение числовых объектов в выражениях интуитивно понятно и просто. В прошлом такой код требовал применения приведений и вызовов методов вроде intValue().
Автоупаковка и распаковка значений классов
Boolean и Как описывалось ранее, Java также поддерживает оболочки для типов boolean и char
— соответственно классы
Boolean и
Character.
Автоупаковка/распаков­
ка также применима к этим типам. Например, рассмотрим следующую программу Автоупаковка/распаковка Boolean и Character.

class AutoBox5 {
public static void main(String a r g s []) {
// Автоупаковка/распаковка boolean.
Boolean b = true;
// b автоматически распаковывается при использовании в условном выражении if.
if(b) System.out.println("b равна true");
// Автоупаковка/распаковка char.
Character ch = 'x'; // упаковка char
char ch2 = ch;
// распаковка char
System.out.println("ch2 равна " + Результат этой программы таков равна true
ch2 равна Наиболее важный момент в этой программе, о котором стоит упомянуть, — это автоматическая распаковка объекта b внутри условного выражения if. Как вы помните, управляющее условие выражения
if при вычислении должно возвращать значение типа boolean. Благодаря автораспаковке, значение типа bool­
ean, содержащееся в объекте Ь, автоматически распаковывается при вычислении условного выражения. То есть с появлением автоупаковки и распаковки стало возможным применять объекты класса
Boolean для управления в операторе i Благодаря автоупаковке и распаковке, объект класса
Boolean теперь также может применяться для управления всеми циклическими конструкциями Java. Когда объект класса
Boolean применяется в качестве условия в выражении while, for или do/while, он автоматически распаковывается в свой эквивалент типа bool­
ean. Например, вот новый допустимый код b;

/ / . .
w h i l e (Ь) { / / . . .

3 0 6 Часть I. Язык Java
Автоупаковка и распаковка помогают предотвратить ошибки
В дополнение к удобству, которое они предоставляют, автоупаковка и распаковка могут также помочь избежать ошибок. Например, рассмотрим следующую программу Ошибка, порожденная "ручной" распаковкой
class UnboxingError {
public static void main(String a r g s []) {
Integer iOb = 1000;
// автоупаковка значения 1000
int i = iOb.byteValue(); // ручная распаковка, как byte !!!
System.out.p r i ntln(i );
// не отображает 1000 Эта программа отображает не ожидаемое значение 1000, а -24! Причина в том, что значение внутри объекта iOb распаковано вручную вызовом метода byte-
V al (), что привело к усечению значения 1000, хранящегося в объекте iOb. В результате получилось мусорное значение -24, которое было присвоено переменной i.
Автораспаковка предотвращает этот тип ошибок, поскольку значение объекта iOb всегда будет автоматически распаковываться в значение, совместимое с типом В общем, поскольку автоупаковка всегда создает правильный объекта автора­
спаковка всегда порождает правильное значение, нет опасности получить неверное значение или неверный объект. В тех редких случаях, когда вам нужно получить значение типа, отличающегося оттого, который создается автоматически, вы можете вручную упаковывать и распаковывать значения. Конечно, выгоды от автоупаковки/ автораспаковки в этом случае теряются. В принципе, новый код должен использовать автоупаковку/автораспаковку. Это — правильный способ написания кода на Java.
Предостережения
Теперь, когда Java включает средства автоматической упаковки/распаковки, некоторые могут подумать, что соблазнительно применять исключительно объекты классов вроде
Integer или
Double, исключая использование элементарных типов. Например, теперь можно написать код вроде следующего Плохое применение автоупаковки/автораспаковки!

Double а, Ь, с;
а = 10.0; b
= с = Math.sqrt(а*а + b * b ) Гипотенуза равна " + с);
В этом примере объекты класса
Double хранят значения, которые используются для вычисления гипотенузы прямоугольного треугольника. Несмотря на то что этот код технически корректен и работает правильно, все же это очень плохое использование автоупаковки/автораспаковки. Он намного менее эффективен, чем эквивалентный код, использующий элементарный тип double. Причина в том
Глава 12. Перечисления, автоупаковка и аннотации (метаданные)
3 0 что автоупаковка и автораспаковка добавляют накладные расходы, которые отсутствуют в случае применения элементарных типов.
Использование оболочек типов следует ограничивать только теми случаями, когда требуется объектное представление элементарных типов. Автоупаковка и автораспаковка были добавлены в Java вовсе не в качестве обходного маневра для исключения элементарных типов.
Аннотации (метаданные)
Начиная с JDK 5 язык Java поддерживает средство, которое позволяет встроить информацию поддержки в исходные файлы. Эта информация, называемая также аннотацией, не меняет действия программы. То есть аннотация сохраняет семантику программ неизменной. Однако эта информация может быть использована различными инструментальными средствами как вовремя разработки, таки в период развертывания. Например, аннотация может обрабатываться генераторами исходного кода. Термин метаданные также используется для именования этого средства, но более описательный термин средства аннотирования программ применяется значительно шире.
Основы аннотирования
Аннотации создаются с использованием механизма, основанного на интерфейсе. Начнем с примера. Вот объявление аннотации под названием
My
Anno.
// Простой тип аннотации MyAnno {
String s t r ();
int v a l (Обратите внимание на символ @, предшествующий ключевому слову interface. Это указывает компилятору, что объявлен тип аннотации. Далее отметим два метода — str (
) и val ()
. Все аннотации состоят только из объявлений методов. Однако тела этих методов вы не определяете. Вместо этого их реализует Java. Более того, методы ведут себя в большей степени подобно полям, как вы вскоре убедитесь.
Аннотация не может включать слова extends. Однако все аннотации автоматически расширяют интерфейс
Annotation. То есть интерфейс
Annotation является суперинтерфейсом для всех аннотаций. Он объявлен в пакете j ava.
lang.
annotation. В интерфейсе
Annotation переопределены методы hashCode
( )
,
equals
() и toString
( ), которые определены в классе
Object. В нем также задан метод annotationType ()
, возвращающий объект класса
Class, который представляет вызывающую аннотацию.
Объявив аннотацию, вы можете использовать ее для аннотирования объявления. Любой тип объявления может иметь аннотацию, ассоциированную с ним. Например, аннотироваться могут классы, методы, поля, параметры и константы перечислений. Аннотированной может быть даже сама аннотация. Во всех случаях аннотация предшествует остальной части объявления.
Когда вы применяете аннотацию, то присваиваете значения ее членам. Например, ниже показан вариант применения аннотации
My
Anno к объявлению метода Аннотирование метода = "Пример аннотации, val = 100)

1   ...   18   19   20   21   22   23   24   25   ...   90


написать администратору сайта