Вы находитесь на странице: 1из 598

2-е издание

Java is
Ра»
'знай, как потоки могут к
изменить твою 'X - ^ thread* C at
W waitO
ч

Накрепко усвой
ж все концепции Java

Научись
программировать
без ошибок

Чувствуй себя
в библиотеке Java
как «рыба в воде»
1 / 1 VI ■
д ■

Развивай скорость Закрепите полученные


соображения знания при помощи
при помощи многочисленных
42 Java-пазлов упражнений

Кэти Сьерра и Берт Бейтс эксм о О REILLY


Head First Java
2nd Ed itio n

Kathy Sierra,
Bert Bates

O ’REILLY*
Beijing • Cambridge • Koln • Sebastopol • Taipei • Tokyo
МИРОВОЙ КОМПЬЮТЕРНЫЙ БЕСТСЕЛЛЕР

Изучаем Java
2-е издание

Кэти Сьерра '^Изучаем Java* зто не просто книга.


Она не только научит вас теории я д о в Java и

и Берт Бейтс о£ьектно~ориентиро0а* iHore программировал,


она сделает Ьас программистом. t? ее основу положен
уникальный мопед обучения на практике.
Ъ отличие cm классические уче/никев информация
дается не &текстовом а 6>визуальном представлении.
Из нее Ь\а узнаете все самое нужнее синтаксис и
концепции изи!ка. работа с потеками, рал. т а в»сети
распределенное программирование рея теория
закрепляется интереснейиллми примерами и
тестами.

эксмо
Москва
2012
Создатели серии Head first
КЭчпи.

К эти Сьерра (Kathy


Sierra) заинтересовалась
теорией обучения, еще
когда была разработчи-
о
ком игровых приложении
(для студий Virgin, M G M
и Amblin). О сновную кон­ Б е р т Б ей тс (B e rt B a te s ) — разработчик про­
цепцию оф ормления серии граммного обеспечения. Когда он трудился
H ead First она придумала, над проблемами искусственного интеллекта
когда преподавала предмет (около десяти л ет), то заинтересовался теорией
«Разработки новых подхо­ обучения и современны м и методиками п реп о­
дов в сфере распростране­ давания. С тех пор он сам преподает програм­
ния информации» в рамках мирование своим клиентам . Н едавно Б ерт стал
курса «Развлекательны е членом команды, разрабаты ваю щ ей сертиф ика­
С М И » в К алифорнийском университете. П о­ ционны е экзам ены для компании Sun.
зж е Кэти слала главным тренером компании
П ервы е десять лет своей карьеры в качестве
Sun M icrosystems, где обучала других тренеров
программиста Б ерт провел в разъездах, сотруд­
технике преподавания современных технологий,
ничал с таким и вещ ательны ми компаниями,
связанны х с Java. В то же время она была веду­
как R adio New Zealand, W ea th e r C hannel и A rts
щ им разработчиком нескольких сертиф икацион­
& E n tertain m en t N etw ork (A & E). О дин из его
ных экзаменов для Jav a -нроф ам м истов. Вместе
самых лю бимы х проектов заклю чался в постро­
с Бертом Бейтсом активно использовала методи­
ении полноценного сим улятора сети ж елезны х
ку излож ения материала, представленную в этой
дорог для компании U nion Pacific Railroad.
книге, чтобы обучить сотни преподавателей, раз­
работчиков и обычных людей, которые не имеют Берт — заядлы й игрок в го, и уже долгое время
отнош ения к программированию. Кроме лого, работает над соответствую щ ей программой.
Кэти — основатель одного из крупнейш их в мире Он прекрасны й гитарист и сейчас пробует
сайтов для Jav a -сообщества javaranch.com и бло­ свои силы в игре на банджо. Л ю бит кататься
га headrush.typepad.com . на лы ж ах, заним ается бегом и тренирует свою
исландскую лош адь Энди (хотя еще неизвестно,
К эти такж е соавтор изданий из серии H ead
кто кого тренирует).
First, посвящ енны х сервлетам, технологии EJB
и ш аблонам проектирования. Б ер т пиш ет книги в соавторстве с Кэти. О ни
В свободное от работы время Кэти заним ается уж е корпят над повой серией изданий (следите
за обновлениям и в блоге).
верховой ездой на своей исландской лош ади, ка­
тается на лы ж ах и бегает, а также пы тается прео­ И ногда его мож но застать на сервере IG C для
долеть скорость свел а. игры в го (под псевдонимом jackStraw ).
kathy@ w ickedlysm art.com terrapin@ w ickedlysm art.com

Кэти и Берт пытаются не оставлять ни одного письма без ответа, но, учитывая количество
посланий и напряженный график командировок, сделать это довольно сложно. Самый
лучший (и быстрый) способ получить техническую помощь по этой книге — обратиться
на очень оживленный форум для новичков в Java: javaranch.com.

6
С одерж ании; (К р а т к о е )
Введение 19
1. Погружаемся 31
2. Путешествие в Объсктвилль 57
3. Свои переменные нужно знать в лицо 79
4. Как себя ведут объекты 101
5. Особо мощные методы 125
6. Использование библиотеки Java 155
7. Прекрасная жизнь в Объектвилле 195
8. Серьезный полиморфизм 227
9. Жизнь и смерть объектов 265
10. Числа имеют значение 303
11. Опасное поведение 345
12. Очень графическая история 383
13. Улучшай свои навыки 429
14. Сохранение объектов 459
15. Устанавливаем соединение 501
16. Структуры данных 559
17. Выпусти свой код 611
18. Распределенные вычисления 637
Приложение А. Итоговая кухня кода 679
Приложение Б. Десять самых важных тем, которым не хватило
самой малости, чтобы попасть в основную часть книга... 689

Введение
Ваш мозг по отношению к Java. Когда вы стараетесь что-то изучить, ваш
мозг пытается оказать вам услугу, убеждая, что все это не имеет никакого значения. Он
думает: «Лучше сосредоточиться на том, как избежать встречи со свирепым хищником
или что обнаженный сноубордист — это плохая идея». Как же убедить мозг в том, что
от знания Java зависит ваша жизнь?

Для кого эта книга 20


Мы знаем, о чем вы подумали 21
Мы знаем, о чем подумал ваш мозг 21
Мстапознание: размышления о мышлении 23
Вот как вы можете подчинить себе свой мозг 25
Что необходимо для чтения этой книги 26
Технические редакторы 28

вы здесь > 7
1
Погружаемся
Java открывает новые возможности. Еще во времена первой (и довольно
скромной) открытой версии 1.02 этот язык покорил разработчиков своим дружественным
синтаксисом, объектно ориентированной направленностью, управлением памятью и, что
важнее всего, перспективой переносимости на разные платформы. Соблазн написать код
один раз и запускать его везде оказался слишком велик. Однако, по мере того как про­
граммистам приходилось бороться с ошибками, ограничениями и чрезвычайной медли­
тельностью Java, первоначальный интерес к языку остывал. Но это было давно. Сегодня
Java достаточно мощный и работает быстрее.
Как работает Java 32
Краткая история Java 34
Структура кола в Java 37
Структура класса 38
Создание класса с методом main 39
Что можно разместить внутри главного метода 40
Зацикливаем, зацикливаем и... 41
Условное ветвление 43
Создание серьезного бизнес-приложения 44
Генератор фраз 47
Упражнения 50

Путешествие в Объектвилль
М Н 6 ГОВОРИЛИ, ЧТО ТОМ б у д у т о б ъ е к т ы . В главе ) вы размещали весь свой
код в методе main(), но это не совсем объектно ориентированный подход. По сути, он
не имеет ничего общего с объектами. Да, вы использовали некоторые объекты, напри­
мер строковые массивы для генератора фраз, но не создавали свои собственные типы
объектов. Теперь вы оставите позади мир процедур, выберетесь из тесного метода
main() и сами начнете разрабатывать объекты. Вы узнаете, чем же так удобно объектно
ориентированное программирование (ООП) на языке Java, и почувствуете разницу
между классом и объектом.

Война за кресло, или Как объекты могут изменить вашу жизнь 58


Создаем первый объект 66
Создание и тестирование объектов Movie 67
Скорее! Выбирайтесь из главного метода! 68
Запускаем нашу игру 70
Упражнения 72

8
Свои переменные нужно знать в лицо
Переменные делятся на два вида: примитивы (простые типы)
И ССЫЛКИ. В жизни должно быть что-то помимо чисел, строк и массивов. Как быть
с объектом PetOwner с переменной экземпляра типа Dog? Или Cat с переменной
экземпляра Engine? В этой главе мы приоткроем завесу тайны над типами в языке Java
и вы узнаете, что именно можно объявлять в качестве переменных, какие значения
присваивать им и как вообще с ними работать.

Объявление переменной 80
Простые типы 81
Ключевые слова в Java 83
IriT
У правление объектом 84
Объект ^ Управление объектом с помощью ссылки 85
Массивы 89
Упражнения 93

Ссылка типа Dog

Как себя ведут объекты


Состояние влияет на поведение, а поведение — на состояние.
Вы знаете, что объекты характеризуются состоянием и поведением, которые пред­
ставлены переменными экземпляра и методами. До этого момента вопрос о связи
между состоянием и поведением не поднимался. Вам уже известно, что каждый экзем­
пляр класса (каждый объект определенного типа) может иметь уникальные значения
для своих переменных экземпляра. Суть объектов заключается в том, что их поведение
зависит от состояния. Иными словами, методы используют значения переменных
зкземпляра. В этой главе вы узнаете, как изменить состояние объекта.

Передавать позначению означает Класс описывает, что объект знает и делает 102
Копироватьпри передаче Передаем методу разные значения 104
Получаем значения обратно из метода 105
Передаем в метод сразу несколько значений 106
Трюки с параметрами и возвращаемыми значениями 109
Инкапсуляция 110
Объекты внутри массива 113
Объявление и инициализация переменных экземпляра 114
int int Разница между переменными экземпляра
foo.go(x); void go (int z){ } и локальными переменными 115
Сравниваем переменные (примитивы или ссылки) 116
Упражнения 118
вы здесь ► 9
Особо мощные методы
Сделаем методы еще более мощными. Вы уже поработали с переменны­
ми, несколькими объектами и написали небольшой код. Но для полноценной работы
требуется гораздо больше инструментов, например операторы и циклы. Почему бы
вам во время учебы не создать что-нибудь настоящее, чтобы собственными глазами
увидеть, как с нуля пишутся (и тестируются) программы. Может быть, это будет игра
вроде «Морского боя».

Создадим аналог «Морского боя»: игра «Потопи сайт» 126


Плавное введение в игру «Потопи сайт» 128
Разработка класса 129
Записываем реализацию метода 131
Тестовый код для класса SimpleDolCom 132
Е Метод checkYousclf() 134
8"

с . Метод main() в игре 140
о Pet5.cc m Поговорим о циклах for 144
Путешествия сквозь цикл 145
Улучшенный цикл for 146
AskMe.c э т Приведение щюстых типов 147
____ 5 ;
Упражнения 148

Использование библиотеки Java


Вместе с Java поставляются сотни готовых классов. Можете не тратить
время на изобретение собственного велосипеда, если знаете, как отыскать нужное
в библиотеке Java, называемой еще Java API. Думаем, у вас найдутся дела поважнее.
При написании кода сосредоточьтесь на той части, которая уникальна для вашего при­
ложения. Стандартная библиотека Java представляет собой гигантский набор классов,
готовых к применению в качестве строительных блоков.
Хорошо, когда известно, что ArrayList Небольшая интрига из предыдущей главы —ошибка 156
находится в пакете java.util. Пи как
Примеры использования ArrayList 163
бы я смогла додуматься до этого
самостоятельно ? Сравнение ArrayList с обычным массивом 166
Исправляем код класса DolCom 168
Новый и улучшенный класс DotCom 169
Создаем настоящую игру «Потони сайт» 170
Что делает каждый элемент в игре DotComBust
(и в какой момент) 172
Псевдокод для настоящего класса DotComBust 174
Окончательная версия класса Dot С о т 180
Супермощные булевы выражения 181
Использование библиотеки (Java API) 184
Как работать с API 188
10 Упражнения 191
Прекрасная жизнь в Объектвилле
Планируйте свои программы с прицелом на будущее. Как вы оцени­
те способ создания Java-приложений, при котором у вас останется много свободного
времени? Заинтересует ли вас создание гибкого кода, которому не страшны досадные
изменения в техническом задании, возникающие в последний момент? Поверьте, вы
можете получить все это лишь за три простых подхода по 60 минут каждый. Изучив принци­
пы полиморфизма, вы узнаете о пяти шагах грамотного проектирования классов, трех
приемах для достижения полиморфизма и восьми способах создания гибкого кода.

Г ' - ,ПгР О я ю Гс,


I
11ринцппы наследования 198
Использование наследования для предотвращения
Црикрепи ЭТО ' дублирования кода в дочерних классах 201

Горь«а*микстура Ищем новые возможности, которые дает наследование 203


Too|
' Л*3етг'РГШоврот Проектирование иерархии наследования 206
Нва^ ат-фигуре Нропопзает суетливо.
Отношения IS-А и HAS-А 207
Н° не наоборот П“°°

XODOUL-C/ НОИеВ^ ° ^ ~ Пиво. Как узнать, что наследование оформлено правильно 209
Z Z что Соч1,1^ ^ ш о и Настоящая ценность наследования 212
Перегрузка метода 221
Упражнения 222

Серьезный полиморфизм
Наследование — это только начало. Чтобы задействовать полиморфизм,
нужны интерфейсы. Новый уровень гибкости и масштабируемости может обеспечить
только архитектура, основанная на интерфейсах. Мы уверены, что вы захотите их ис­
пользовать. Вы удивитесь, как могли жить без них раньше. Что такое интерфейс? Это на
100 % абстрактный класс. Что такое абстрактный класс? Это класс, для которого нельзя
создать экземпляр. Зачем это нужно? Читайте главу...

Object о = al.get(id) ;
Dog d = (Dog) o; Абстрактный против Конкретного 232
d.bark (); ' " 233
Абстрактные методы
Полиморфизм в действии 236
Класс Object 238
Использование полиморфических ссылок типа Object 241
Интерфейс спешит на помощь! 254
Упражнения 260
Object
Т ие°9юи q i ,
l( ^ y o o a Z ect
Ъ нмы ^

“« " С 8*104
вы здесь > 11
Жизнь и смерть объектов
ОбъеКТЫ роЖДаЮТСЯ И умирают. Вы управляете их жизненным циклом. Вы ре­
шаете, когда и как создавать их. И вы решаете, когда их уничтожать. Но на самом
деле вы не уничтожаете их, а просто делаете брошенными и недоступными. Уже после
этого безжалостный сборщик мусора может аннулировать объекты, освобождая ис­
пользуемую память. В этой главе мы рассмотрим, как создаются объекты, где размеща­
ются, как эффективно использовать их и делать недоступными.

Стек и куча: где все хранится 266


Методы размещаются в стеке 267
Как работают локальные переменные,
являющиеся объектами 268
Создание объекта 270
Создаем объект Duck 272
Инициализация состояния нового объекта Duck 273
Роль конструкторов родительского класса в жизни объекта 274
Как вызвать конструктор родительского класса 283
Конструкторы родительских классов с аргументами 285
Вызов одного перегруженного конструктора из другого 286
Переменкой 4 присвоен. коЙлй оЭьектп
Duck. Чщо ое/ыечг, пер&ш о§Ъеют| Сколько живет объект 288
к е э о с ^ н Ш Л U o ecw.b п р и ч е с к и Упражнения 296
Мер’гпблм).

Числа имеют значение


Поговорим о математике. В Java API есть множество удобных и простых
в использовании методов для работы с числами. Поскольку большинство из них
статические, то сначала разберемся, какими особенностями обладают статические
Статические
переменные переменные и методы, включая константы, которые в Java считаются статическими
уииверсальиы финализированными переменными.
для всех
экземпляров
класса. Математические методы — наиболее близкие к глобальным 304
ОтСПЦ1»Ч£СК<Л Разница между обычными (нс статическими)
и статическими методами 305
Tie реме киЬае Что значит иметь класс со статическими методами 306
Эхзедплягх Инициализация статической переменной 311
(iWtSi): па ООной
Ил Эк^е/АПЛЯр. Автоматическая упаковка: стираем границы между
примитивом и объектом 319
Синодические
Г)ереленн1ле: по
Форматирование чисел 324
ой на класс. Спецификатор форматирования 328
Работа с датами 332
Работа с объектами Calendar 335
Основные методы класса Calendar 336
Статический импорт 337
Упражнения 340
12
Опасное поведение
Случается всякое. То файл пропадает, то сервер падает. Не важно, насколько хорошо
вы программируете, ведь невозможно контролировать все. Что-то можёт пойти не так. При
создании опасного метода вам понадобится код, который будет обрабатывать возможные
нестандартные ситуации. Но как узнать, опасен ли метод? И куда поместить код для обра­
ботки непредвиденной ситуации? В этой главе мы разработаем музыкальный MIDI-проиг­
рыватель, использующий опасный JavaSound API.
Что происходит, если вы вызываете опасный метод 349
Методы в Java используют исключения, чтобы сообщить
вызывающему коду: «Случилось нечто плохое. Я потерпел неудачу». 350
Исключение —объест типа Exception 352
Управление программным потоком в блоках try /catch 356
Finally: для действий, которые нужно выполнить несмотря ни на что 357
Исключения поддерживают полиморфизм 360
Приложение для проигрывания звуков 372
Создание M IDI-событий (данных о композиции) 373
M IDI-соибщсиие: сердце MidiEvent 374
Как изменить сообщение 375
Кухня кода 369
Упражнения 378

Очень графическая история


Соберитесь, вам предстоит придумать GUI (graphical user interface — гра­
фический пользовательский интерфейс). Даже если вы уверены, что всю оставшу­
юся жизнь будете писать код для серверных программ, где работающий на клиентской стороне
пользовательский интерфейс представляет собой веб-страницу, рано или поздно вам придется
создавать инструменты и вы захотите применить графический интерфейс. Работе над GUI по­
священы две главы, из которых вы узнаете ключевые особенности языка Java, в том числе та­
кие, как обработка событий и внутренние классы. В этой главе мы расскажем, как поместить
на экран кнопку и заставить ее реагировать на нажатие. Кроме того, вы научитесь рисовать на
экране, добавлять изображение в формате JPEG и даже создавать анимацию.
Ваш первый графический интерфейс: кнопка во фрейме 385
class MyOuter { Пользовательское событие 387
else я HyJtraiar ( Слушатели, источники и события 391
void go (J \-ft
Вернемся к графике... 393
i
> Личный виджет для рисования 394
» Что интересного можно сделать в paintComponent() 395
За каждой хорошей графической ссылкой стоит объект Graphics2D 396
Компоновка графических элементов: помещаем
несколько виджетов во фрейм 400
Попробуем сделать это с двумя кнопками 402
Как создать экземпляр внутреннего класса 408
Используем внутренний класс для анимации 412
Легкий способ создания сообщений/событий 418
Кухня кода 416
Упражнения 424

вы здесь ► 13
Улучшай свои навыки
Swing — это просто. Код для работы со Swing выглядит просто, но, скомпили­
ровав его, запустив и посмотрев на экран, вы подумаете: «Эй, этот объект должен быть
в другом месте». Инструмент, который упрощает создание кода, одновременно услож­
няет управление им — это диспетчер компоновки. Но, приложив небольшие усилия,
вы можете подчинить диспетчер компоновки. В этой главе мы будем работать со Swing
и ближе познакомимся с виджетами.

ftoMnoKfi-H.Tr.U Компоненты Swing 430


£ oS/клстпЯх Диспетчеры компоновки 431
east и. "west
Как диспетчер компоновки принимает решения 432
по Три главных диспетчера компоновки: border, flow и 1юх 433
Ctnar jj Играем со Swing-компонептами 443
Кол\покеа>я(л
ё о5/цстг|5(х ■eion Полу^4- Кухня кода 448
П°г$1 и south ' CClTlfU^I Упражнения 454
ЙлтпЯгиёйкппсЯ South
^^яину.

Сохранение объектов
Объекты могут быть сплющенными И восстановленными. Они харак­
теризуются состоянием и поведением. Поведение содержится в классе, а состояние
определяется каждым объектом в отдельности. Что же происходит при сохранении
состояния объекта? Если вы создаете игру, вам понадобится функция сохранения/вос-
становления игрового процесса. Если вы пишете приложение, которое рисует графи­
ки, вам также необходима функция сохранения/восстановления. Вы можете сделать
это легким объектно ориентированным способом — нужно просто сублимировать/
сплющить/сохранить/опустошить сам объект, а затем реконструировать/надуть/вос-
становить/наполнить его, чтобы получить снова.
Сохранение состояния 461
Запись сериализованного объекта в файл 462
Что на самом деле происходит с объектом при сериализации 464
.tepu^ujc&iHHbiu
Десериализация: восстановление объекта 471
Сохранение и восстановление игровых персонажей 474
Запись строки в текстовый файл 477
Пример текстового файла: электронные флеш-карты 478
г , - * * * ? 0* 1
Quiz Card Builder: структура кода 479
ДесериЛЛЦЗ° & *ннЫ и
’Ч Класс java.io.File 482
Чтение из текстового файла 484
Quiz Card Player структура кода 485
Разбор текста с помощью метода split() из класса String 488
Использование serialVersionUlD 491
Сохранение схемы BealBox 493
Восстановление схемы BeatBox 494
Кухня кода 492
14 Упражнения 496
Устанавливаем соединение
Свяжитесь с внешним миром. Это просто. Обо всех низкоуровневых се­
тевых компонентах заботятся классы из библиотеки java.net. В Java отправка и по­
лучение данных по Сети — это обычный ввод/вывод, разве что со слегка изменен­
ным соединительным потоком в конце цепочки. Получив класс BufferedReader, вы
можете считывать данные. Ему все равно, откуда они приходят — из файла или по
сетевому кабелю. В этой главе вы установите связь с внешним миром с помощью
сокетов. Вы создадите клиентские и серверные сокеты. В итоге у вас будут клиен­
ты и серверы. И вы сделаете так, чтобы они смогли общаться между собой. К концу
этой главы вы получите полноценный многопоточный клиент для чатов. Ой, мы
только что сказали «многопоточный»?

Чат в BeatBox в режиме реального времени 502


Подключение, отправка и прием 504
Устанавливаем сетевое соединение с помощью сокета 505
BufferedReader для считывания данных из сокета 508
PrintW riter для записи данных в сокет 509
DailyAdviceClicnt 510
Код программы Daily Ad viceClient 511
Создание простого сервера 513
Код приложения DailyAdviceServer 514
S S Создание чат-клиента 516
Несколько стеков вызовов 521
Планировщик потоков 527
Приостановление потока 531
Метод sleep() 532
Создание и запуск двух потоков 533
Использование блокировки объектов 541
Новая улучшенная версия SimpleChatClicnt 548
Очень-очень простой чат-сервер 550
Упражнения 554

вы здесь ► 15
Структуры данных
Сортировка в Java — проще простого. У вас уже есть все необходимые ин­
струменты для сбора данных и управления ими, поэтому не нужно писать собственные
алгоритмы для сортировки. Фреймворк для работы с коллекциями в Java
(Java collections framework) содержит структуры данных, которые должны подойти
практически для всего, что вам может понадобиться. Хотите получить список, в кото­
рый можно добавлять элементы? Вам необходимо найти что-нибудь по имени? Хотите
создать список, который автоматически убирает все дубликаты? Желаете отсортиро­
вать своих сослуживцев по количеству ударов, которые они нанесли вам в спину, или
домашних любимцев по количеству трюков, которые они выучили? Читайте главу...

Коллекции 561
Сортировка ArravList методом Collections.sort() 564
Обобщения и безопасность типов 570
Коллекция API — List (Список), Set (Множество) и Мар
(Отображение, или Ассоциативный массив) 587
Переопределение hasbCode() и equais() 591
Использование полиморфических аргументов и обобщений 599
Упражнения 606

Выпусти свой код


Пришло время его отпустить. Вы написали код. Вы его протестировали
и откорректировали. Вы рассказали всем знакомым, что больше не желаете видеть ни
единой его строки. По большому счету вы создали произведение искусства. Это то, что
действительно работает! Но что дальше? В последних двух главах мы расскажем, как
организовывать, упаковывать и развертывать (внедрять или доставлять) код на языке
Java. Мы рассмотрим локальный, полулокальный и удаленный варианты развертыва­
ния, включая исполняемые Java-архивы (JAR), Java Web Start, RMI и сервлеты. Большую
часть этой главы мы посвятим организации и упаковыванию вашего кода — это то, что
нужно знать вне зависимости от выбранного варианта доставки.

--------
corn i Варианты развертывания 612
Отделение исходных файлов от скомпилированных 614
Помещаем программу в J AR-архнв 615
MyApp.jor
Помещаем классы в пакеты 617
ISAyApp.class
Предотвращение конфликтов при именовании пакетов 618
Компилируем и запускаем, используя пакеты 620
Флаг -d 621
Создание исполняемых Java-архивов с пакетами внутри 622
!Java Web Start 627
JN LP-файл 629
Упражнения 631
16
Распределенные вычисления
Находиться далеко — это не всегда плохо. Конечно, задача упрощает­
ся, когда все компоненты приложения собраны в одном месте и всем этим управляет
одна JVM. Но это не всегда возможно. И это не всегда целесообразно. Как быть, если
ваше приложение выполняет сложные вычисления и должно работать на маленьком
симпатичном пользовательском устройстве? Что делать, если вашему приложению
нужна информация из базы данных, но в целях безопасности к ней может полу­
чить доступ только код на вашем сервере? Мы также познакомимся с технологиями
EnterpriseJavaBeans (EJB) и Jini, узнаем, в каких случаях их работа зависит от RMI.
Последние страницы книги будут посвящены созданию одной из самых потрясающих
программ — обозревателя универсальных сервисов.

Клиент Технология RMI 644


Создание удаленного сервиса 645
Сервлеты 655
EnterpriseJavaBeans 661
Немного о Jini 662
Создаем обозреватель универсальных сервисов 666

Приложение А
Итоговая кухня кода. Финальная версия серверной части программы 8eat8ox.

Итоговый вариант клиентской программы BeatBox 680


Итоговый вариант серверной части программы Beat Box 687

Приложение Б

Б Десять самых важных тем, которым не хватило самой малости,


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

Топ-десять 689

У казател ь 709

вы здесь > 17
Как читать эту книгу

Введение
Не могу поверить,
что они поместили
это в книгу
1программировании
L на Jova! г*

ЗоесЬ с а к ий ж и & гт р е п е и ^ ш м й fo n p
«ТЬЧеМ ч Ж е они п о м е с т и л и Эгпо Ъ кн и г\)
о ^рогрлМ М иро^киа кд Jd v d ?*

19
Как читать эту книгу

Аля кого э т а книга


Если в ы утвердительно ответите на все эти Это не с п р а в о ч н и к .
вопросы: Книга предназначена
д л я и зучени я Java
Вы когда-нибудь программировали? и не с о д е р ж и т
энциклопедических
Вы хотите изучить язык Java? с в е д е н и й об этом
язы ке.
Вы предпочитаете непринужденный
разговор на званом обеде вместо
сухой, скучной технической лекции?
тогда эта книга для вас.

Кому лучшедержаться подальше от книги


Если в ы утвердительно ответите на любой из этих вопросов:

( | ) Ограничивается ли ваш опыт


программирования одним HTML,
без сценарных языков?
Если вы имели дело с лю бы ми циклам и и зн ак о ­
мы с условиям и if/th en , книга вам подойдет, но
одной разметки H T M L мож ет бы ть недостаточно.

($) Вы опытный программист на языке C++


и ищете справочник!?

(3) Вы боитесь пробовать что-то новое? Вы


скорее отправитесь на прием к дантисту,
чем наденете полосатые брюки вместе
с клетчатой рубашкой? Считаете ли вы,
что книга не может быть серьезной, если
в одном из ее разделов, посвященном
управлению памятью, нарисован утенок?

то эта книга не для вас.

20 введение
Введение

Мы зизем, о чем Ьь\ подумали


«Н асколько эта книга о программировании па Jav a серьезна?»
«Ч то это за иллю страции?»
т ь
«М огу л и я изучит ь материал, подаваемы й в таком виде?»
«Это случайно нс пиццей пахнет?» Но.
о ^ Н""и у о

Мы знаем, о чем подумал &аш мозг


Ваш м озг ж аж дет нового. Он постоянно ищ ет и ожидает необы ч­
ны х событий. О н так устроен, и это помогает вам в ж изни.
В нынеш нее время вы вряд ли станете завтраком д л я тигра. Н о ваш
мозг всегда настороже. Вы просто этого не замечаете.
Как же он поступает с обычными вещами, с которы ми вы стал ­
киваетесь? Он делает все, чтобы они не меш али ему запом инать
действительно важ ную информацию . Он не обращ ает вним ания на
скучны е и очевидно бесполезные вещи, беспощ адно их ф ильтруя.
О ткуда ж е ваш ему мозгу известно, что важ но? П редполож им, вы
вы ш ли прогуляться, и тут на вас набросился тигр. Ч то будет тво ­
риться в вашей голове?
Н ейроны накалятся. П редельная концентрация. Хим ический вщ тв.
Вот откуда ваш мозг знает...
Это очень важно! Не забудь!
А теперь представьте, что вы находитесь дома или в библи
отеке. Это безопасное и уютное место, совсем без тигров.
Вы что-то читаете. Готовитесь к экзам ену или пытаетесь
вы учить слож ную техническую тем у за неделю, максимум
за десять дней (чего, по мнению вашего начальника, д о л ж ­
но бы ть достаточно).
Н о есть одна проблема. Ваш мозг хочет оказать вам
услугу. О н пы тается принять меры, чтобы вся эта оче­
видно ненуж ная инф орм ация не отним ала у вас столь
деф ицитны е ресурсы. Ресурсы, которы е лучш е потра­
тить на запом инание по-настоящ ему важ ных вещей.
Т аких как тигры, угроза пожара, обещ ание никогда не
кататься на сноуборде в шортах.
И нельзя просто сказать мозгу: «М озг, спасибо боль­
шое, но какой бы скучной ни бы ла эта книга и как бы
мало эм оций она у меня ни вызывала, я, правда, хочу
запом нить то, что в ней написано».

вы здесь ► 21
Как читать эту книгу

$ foAu> чаиьаиьсдя эты& кшш> мы Хотели, бы &и$сун.ь человека. &отьо]>ы£1 дюбидк. уч&тш^г.
Что же нужно для того, чтобы что-нибудь выучить? Прежде всего вы должны понять прочи­
танное и убедиться, что не забудете новую информацию. Речь идет не о зубрежке фактов.
Согласно последним исследованиям в области когнитивистики, нейробиологии и педаго­
гической психологии, процесс обучения — это нечто намного большее, чем просто чтение
текста. Мы знаем, что заставляет мозг работать.

Несколько принципов, на которых основана эта книга.


В и з у а л и з а ц и я . Изображения запоминаются намного лучше,
чем обычные слова, и с ними обучение становится более
эффективным (увеличение запоминания и восприимчивости
/ Meejor
вплоть до 89 %). Это также делает информацию понятнее.
П ри р а зм е щ е н и и с л о в в н у тр и с о о т в е т с т ­
в у ю щ и х и л л ю с т р а ц и й и л и р я д о м с ним и
вероятность возникновения у читателей проблем,
связанных с содержимым книги, снижается почти
вдвое (по сравнению с классической подачей материала,
когда текст находится внизу или вовсе на другой странице).

Р а з г о в о р н ы й с т и л ь и п е р с о н и ф и к а ц и я . Новейшие исследования показы­


вают, что студенты справляются с итоговыми тестами почти на 40 % лучше, если
учебники написаны от первого лица с применением разговорного стиля вместо
официального. Рассказывайте истории, а не читайте лекции. Используйте нефор­
мальный язык. Не будьте слишком серьезными. Что бы вас больше заинтересова­
ло — интересное общение на званом обеде или прослушивание лекции?

П о п ы тк а сд е л а ть т а к , ч то б ы ч и та те л ь б о л ее гл у б о к о вн и к
в с о д е р ж и м о е . Иными словами, пока вы не начнете активно
напрягать свои нейроны, в вашей голове ничего не родится. Можно ли сказать, что
Чита гель должен быть достаточно мотивирозан, заинтере­ ванна — это ванной
комната? А наоборот?
сован, заинтригован и вдохновлен, чтобы решать проблемы, Или одно содержит
делать выводы и генерировать новые знания. А для другое?
го ал н ) ; этог° нужны испытания, упражнения и вопросы,
■р заставляющие задуматься; нужно сделать так, чтобы в про-
*1* цессе обучения участвовали обе доли головного мозга и разные
V, * * * £ * * * * уровни сознания.

З а в о е в а н и е и у д е р ж а н и е в н и м а н и я ч и т а т е л я . Все мы
сталкивались с ситуацией, когда действительно нужно что-то выучить, но
после первой же страницы клонит в сон. Мозг интересуется неординарными, интересны­
ми, странными, яркими и неожиданными вещами. Изучение нового сложного техниче­
ского материала будет проходить намного быстрее, если вам не будет скучно.

Э м о ц и и . Нам уже известно, что способность к запоминанию чего-либо во многом зависит от


эмоциональной составляющей. Вы запоминаете то. что для вас важно. Вы запоминаете, когда что-то
чувствуете. Нет, мы имеем в виду не душещипательные истории. Под эмоциями мы подразуме­
ваем удивление, любопытство, веселье. Это ситуации, когда мы задумываемся над материалом
и чувствуем удовлетворение от того, что решили головоломку, выучили то, что остальные считают
сложным, или понимаем, что знаем нечто такое, чего не знает наш заносчивый приятель Боб,
который якобы более подкован в технических вопросах.
'" 'Г, — - '■
----------- "тт
введение
Введение

Интересно,
Метапозизиие: размышления о мышлении как мне заставить
свой мозг запомнить
Если вы действительно хотите ускорить процесс обучения, обратите вним а­ все это...
ние на то, как вы обращ аете внимание. П одумайте над тем, как вы думаете.
И зучите го, как вы учитесь.
Б ольш инство из нас не оканчивали курсы м етапознания и не знаком ы с тео­
рией обучения. М ы планировали учиться, а не «учить, как нуж но учиться».
Н о мы предполагаем , что, если вы держ ите в руках эту книгу, то хотите
вы учить язы к Java. И , вероятно, не ж елаете трати ть на это слиш ком много
времени.
Ч тобы получить максимальную пользу от этой (и л и любой
другой) книги, возьмите на себя ответственность за свой
мозг. З а то, как он поступит с новым материалом.
Х итрость заклю чается в том, чтобы заставить мозг думать
о новом м атериале как о чем-то по-настоящ ему важном,
как будто от этого зави си т ваше благосостояние. С ловно
перед вами тигр. В ином случае вы обречены на посто­
янную войну со своим мозгом в попы тках заставить его
запом нить новый материал.

К ак же заставить свой мозг воспринимать Java словно это не язы к


программирования, а голодный тигр?
М ож но пойти двум я путями: медленны м и скучны м или более бы стрым и эф ф ек ти в­
ным. М едленны й путь — обычная зубреж ка. Вам, конечно, известно, что упорство
и труд перетрут даж е самый неинтересны й материал. При достаточном количестве
повторений ваш м озг рано или поздно решит: «Я не думаю, что эта вещь для него
важна, но раз он продолж ает смотреть на нее снова и снова, то, наверное, в ней что-то
есть».
Бы стры й путь заклю чается в повышении мозговой активности, в частности разны х
ее типов. Н а преды дущ ей странице мы уже описали больш инство подходов, п р и зван ­
ных помочь ваш ему мозгу работать в ваш их же интересах. Н апример, исследования
показы ваю т, что разм ещ ение слов внут ри и зображ ений, которы е их иллю стрирую т
(а не в заголовке или в основном блоке текста), застав л яет мозг искать св язь меж ду
текстом и картинкой, что приводит в действи е больш е нейронов. Б ольш е н ей ро­
нов — это больш е ш ансов, что м озг сочтет потребляем ую и нф орм ац ию стоящ ей
и зап о м н и т ее.
П омогает и разговорны й стиль излож ения. Л ю ди имею т склонность больш е сосре­
дотачиваться, когда к ним кто-то обращ ается; они отслеж иваю т мысль, чтобы под­
держ ать беседу. С лож но поверить, но ваш м озг мож ет проигнорировать тот факт,
что «беседа» ведется между вами и книгой! С другой стороны, если книга вы держ ана
в оф ициальном и сухом стиле, ваш мозг будет вести себя так, словно вы слуш аете л е к ­
цию в аудитории, наполненной сонны ми студентами. Н ет нужды сосредотачиваться.
Н о иллю страции и разговорный стиль — это только начало.
вы здесь > 23
Как читать эту книгу

# о т что мы сделали
Мы использовали изображения, потому что мозг приспособлен к восприятию
визуальной информации, а не текста. С его точки зрения, картинка действи­
тельно стоит 1024 слов. Мы поместили ключевой текст' внутрь иллюстрации,
на которые он ссылается, а не в заголовок или куда-либо еще, потому что так
мозг работает более эффективно.
Мы задействовали повторения, выражая одни и те же вещи разными спосо­
бами и с помощью разных материалов, увеличивая шансы на то, что информа­ ПоработклилК.с
ция будет закодирована сразу в нескольких участках вашего мозга.
KoMHU>/tyT»bo]>oM
Мы использовали понятия и изображения так, чтобы вас удивить , потому что
мозг приспособлен к восприятию чего-то нового. Мы ввели некую эмоциональ­
ную составляющую, потому что мозг восприимчив к биохимии эмоций. Бла­
годаря этому вы чувствуете, что данную информацию лучше запомнить, даже
если ощущение основано лишь на юморе, неожиданности или интересе.
Мы применяли персонифицированный, разговорный стиль изложения, так
как мозг больше сосредотачивается при общении, а не во время пассивного
просмотра презентации. Такой подход срабатывает даже при чтении.
Мы добавили более 50 упражнений, так как мозг может выучить и запом­
нить больше, если вы выполняете какие-то вещи, а не просто читаете о них.
Мы сделали упражнения сложными, но выполнимыми, потому что именно
этого хотят большинство людей.
Мы использовали несколько стилей подами материала, ведь все люди |>аз-
иыс. Одни могут отдавать предпочтение пошаговым методикам, другие хотят
сначала понять общую картину, третьим нужно увидеть пример кода. Но вне
зависимости от личных пристрастий каждый читатель получает пользу от
знакомства с материалом благодаря разным подходам. КЛЮЧЕВЫЕ МОМЕНТЫ
Мы подготовили материал для обеих половин вашего мозга, потому что чем
больше его участков вы задействуете, тем лучше пройдет обучение и запоми­ РА ЗОЬа АЧ Ь Н И Е
нание и тем дольше вы сможете оставаться сконцентрированным. Поскольку
нагрузка на одну половину мозга означает, что у другой сеть шанс отдохнуть, ЯЗЫ КА <М УА
ваши занятия становятся более продуктивными и продолжительными.
Мы также включили в книгу рассказы и упражнения, которые предоставля­
ют несколько разных точек зрения, так как ваш мозг более глубоко вникает
в проблему, если заставить его давать оценки и делать выводы.
Помимо упражнений мы добавили сложные задачи, ставя в них вопросы,
на которые не всегда можно ответить однозначно. Это связано с тем, что мозг д л я мозга
лучше обучается и запоминает во время какой-то работы (то же самое с вашим
телом —чтобы поддерживать его в хорошей <}юрме, недостаточно наблюдать
за посетителями фитнес-клуба). Но мы сделали вес от нас зависящее, чтобы
направить ваши усилия в правильное, русло. Мы старались, чтобы вы не потра­
тили ни одного лишнего дендрита па работу с тяжелым для понимания приме­
ром или на разбор сложного либо, наоборот, чрезмерно лаконичного текста.
Мы использовали закон Парето (или принцип 8 0 /20) и исходили из того, что,
если вы хотите получить ученую степень в Java, это будет нс единственная
книга, которую вы прочтете. Поэтому мы не пытались рассказать обо всем.
Мы рассматривали только те вещи, которые вам действительно пригодятся.

24 введение
t?om как Ь\л можете подчинить
себе, с&ой мозг
Итак, свою работу мы в ы п о л н и л и . Д альш е все зави си т от вас. Эти
советы — лиш ь отправная точка. П рислуш ивайтесь к своему мозгу
и сами определяйте, какие пункты вам подходят, а какие — нет.
М ожете попробовать что-нибудь новое.
РБсрежЬт^е Этг)о и приклейте нд с£ой холо^^Ькик.

Не спешите. Чем больше вы поймете, Пейте воду. Много воды.


тем меньше вам придется запоминать. Лучше всего мозгу работается во влажной
Недостаточно просто читать. Нужно среде. Обезвоживание (которое может
останавливаться и обдумывать прочитанное. наступить даже до того, как вы почувствуете
Когда в книге вам задается вопрос, нс пропу­ жажду) снижает способность к познанию.
скайте его. Представьте, что кто-то действи­ Разговаривайте о прочитанном. Вслух.
тельно вас спрашивает. Чем более глубоко При ралтворе активизируются разные части
вы заставите свой мозг вникать в материал, мозга. Если вы пытаетесь что-то понять или
гем больше у вас шансов что-нибудь выучить хотите с большей долей вероятности запом­
и запомнить. нить прочитанное, попробуйте произнести
Выполняйте упражнения. Делайте эго вслух. А еще лучше попытайтесь объяснить
слои заметки. это на словах кому-нибудь другому. Процесс
Мы включили их в книгу, но не будем делать изучения ускорится, и у вас могут появиться
их за вас — это как тренироваться вместо идеи, о которых вы не задумывались при
другого человека. К{юме того, недостаточно чтении.
только смотреть на них. П о льзуй тесь к а ­ ^8 ) Прислушивайтесь к своему мозгу.
рандашом. Давно доказано, что физическая Следите за тем, чтобы ваш мозг не был пере­
активность во время занятий способствует гружен. Если вы начинаете поверхностно
процессу обучения. воспринимать или забывать только что про­
Читайте «Это не глупые вопросы». читанный текст, значит, пришло время сде­
Все без исключения! Это не дополнение, лать перерыв. Пройдя определенный рубеж,
а часть основного материала! Иногда вопро­ вы уже не сможете ускорить свое обучение,
сы более полезны, чем сами ответы. увеличивая объем материала. Более того, это
может даже навредить.
Не читайте книгу в одном месте.
0 Чувствуйте что-нибудь!
Встаньте, разомнитесь, подвигайтесь, пере­
сядьте на другое кресло, перейдите в другую Вашему мозгу нужно знать, что это важно.
комнату. Это поможет вашему мозгу что-то Пытайтесь прочувствовать рассказы, кото­
почувствовать и не даст вам слишком тесно рые читаете. Делайте собственные заголовки
ассоциировать учебу с конкретным местом. для рисунков. Вздохнуть от плохой шутки
все же лучше, чем совсем ничего не ощутить.
Постарайтесь, чтобы эта книга была
последней перед сном. По крайней ,jp) Набирайте и запускайте код.
мере не читайте после нее ничего, что Набирайте и запускайте код из примеров.
бы вас напрягало. Потом вы сможете экспериментировать, из­
меняя и улучшая его (или переписывая пол­
Процесс изучения (особенно сохранение
информации в долговременной памяти) ностью -- это иногда лучший способ понять,
что происходит на самом деле). Длинные
частично происходит после того, как вы
примеры или заранее подготовленный код
откладываете книгу в сторону. Мозгу нужно
можно загрузить в виде исходных файлов
время, чтобы обработать прочитанное. Если
с cairra heaclfirstjava.com.
во время этого процесса вы попытаетесь
запомнить что-то новое, то часть изученного
материала будет утрачена. вы здесь > 25
Как читать эту книгу

Что необходимо Зля чтения э т о й книги


Вам не нужны дополнительны е инструменты , в том числе интегрированная среда
разработки (ID E ). М ы настоятельно рекомендуем вам не использовать ничего,
кроме простого текстового редактора, пока вы не дочитаете эту книгу ( особенно
до окончания главы 16). ID E мож ет скры ть от вас действительно важ ны е детали,
поэтому при изучении язы ка лучш е пользоваться командной строкой, а уж е потом,
вникнув в происходящ ее, перейти к работе с инструментами, которы е автом атизи ­
рую т процесс разработки.
----ПОДГОТОВКА ИНСТРУМЕНТОВ ДЛЯ JAVA--------------------------------
■ Если у вас еще нет пакета Java 2 Standard Edition SDK (Software Development Kit —
комплект средств разработки) версии 1.5 или выше, придется его установить. Если вы
работаете в Linux, Windows или Solaris, то можете получить его бесплатно на сайте java.
sun.com (сайт компании Sun для Ja v a -программистов). Обычно загрузка J2SE занимает
не больше двух щелчков кнопкой мыши на главной странице. Вам нужна последняя
стабильная (не beta) версия. SDK содержит все, что необходимо для компиляции и запуска
программ на языке Java.
Если вы работаете с Mac OS X 10.4, то Java SDK у вас уже установлен и вам не нужно
выполнять дополнительных действий. Предыдущие версии OS X содержат более ранние
версии Java, которые, впрочем, совместимы с 95 % кода из этой книги.
Примечание: книга основана на Java 1.5, но по непонятным маркетинговым причинам
вскоре после выпуска компания Sun переименовала эту версию в Java 5, сохранив при этом
обозначение 1.5 для комплекта разработки. Поэтому, встречая такие названия как Java 1.5,
Java 5, Java 5.0 или Tiger (изначальное кодовое имя пятой ветки), знайте, что это одно
и то же. Java 3.0 или 4.0 никогда не существовал — был сделан скачок с версии 1.4 к 5.0,
но в некоторых местах еще используют обозначение 1.5 вместо 5. Еще один интересный
момент — Java 5 и Mac OS X 10.4 получили одно и то же кодовое имя — Tiger, поэтому
иногда вы можете услышать, как люди говорят о «Тигре на Тигре». Это всего лишь означает
«Ja va 5 на OS X 10.4».
■ SDK не содержит документации по API, но она вам нужна! Вернитесь на сайт java.sun.com
и загрузите документацию по J2SE API. Можно читать ее прямо в браузере, но это очень
неудобно. Лучше все же загрузить.
■ Вам нужна программа для набора текста. В сущности, подойдут любые текстовые
редакторы (vi, emacs, pico), включая поставляемые вместе с операционными системами.
Блокнот, WordPad, TextEdit и т. д. — все сгодятся (только следите, чтобы к названиям
ваших исходных файлов не добавлялось расширение .txt).
■ Загрузив и распаковав SDK (метод распаковки зависит от версии вашей ОС), нужно
добавить в переменную среды PATH значение, которое указывает на директорию /bin
внутри главного каталога с Java. Например, если J2SDK помещен в директорию j2sdk1.5.0
на вашем диске, то в ней вы найдете каталог bin, хранящий утилиты (инструменты). Его
нужно добавить в PATH, чтобы при наборе
% ja v a c
в командной строке ваш терминал знал, где искать компилятор javac.
Примечание: если у вас возникли проблемы с установкой, сходите на сайт javaranch.com
и присоединитесь к форуму Java-Beginning! Хотя вам стоит сделать это в любом случае.

Еще одно примечание: большая часть кода из этой книги доступна на сайте wickedlysmart.com.

26 введение
Введение

frue кое-что, о чем вам нужно зн ать fNbi хС.Г|ОЛЬЗУ

г
П '
Н аш а книга основана на реальном опыте, это не справочник. Мы ум ы ш лен­ fKOj№
но вы бросили из нее все, что мож ет помешать изучению подготовленного псе'% 0 'M U
нами материала. Н уж но начать с первых страниц, так как дальш е и нф орм а­
ция подается исходя из того, что вы уже видели и выучили.

Мы используем простые диаграммы, похожие на (IM L.


Если бы мы воспользовались настоящим U M L, вы бы увидели нечто
похожее на Java, но с абсолютно неправильным синтаксисом. П оэтому мы
прибегли к упрощ енной версии UM L, которая нс противоречит синтаксису
Java. Если вы еще не знаете UM L, не волнуйтесь — вы сможете изучить его
вместе с ) w a .

Мы ие обращаем внимания на организацию и оформление


8сЛпр4Ж*-еКиЯ п°9
кода вплоть до заклю чительных глав.
С этой книгой вы можете непосредственно изучать язы к Java, не отвлекаясь свой карандаш*-
на организационны е и адм инистративны е подробности. В реальном мире
вам придет ся знать и использовать эти вещи, поэтому они тож е будут рас­ Н аточите
смотрены . Но мы приберегли их для предпоследней главы 17. Расслабьтесь
свой карандаш
и спокойно погруж айтесь в мир Java.

Уп§>ажне2§Ш8, которыми заканчиваются главы, обязатель­


ны для выполнения; ГШЮВСШвЖйМ — на ваше усмотрение.
Ответы и решения размещаются в конце каждой главы .
Все, что вам нуж но знать о головоломках, — над ними нуж но ломат ь голову.
К ак и над логическим и загадками, задачами с подвохом, кроссвордами
и т. д. Упраж нения нужны для того, чтобы помочь вам прим енить получен­
ные зн ан и я на практике, и придется вы полнить каж дое из них. С голово­
лом кам и все иначе, и некоторые довольно слож ны е в своем роде. Голово­
лом ки созданы для тех, кто лю бит их решать, и вы уже, наверное, знаете,
относитесь ли вы к их числу. Но если вы не уверены, то просто попробуйте
и не отчаивайтесь, если ничего не получится. Упражнение
У упражнений под заголовком «Наточите свой карандаш»
нет ответов. ,о/л
Толовопв*» р iV1A-O1о&У4-
По крайней мере в этой книге их нет. На часть из них просто нельзя отве­ нд^1
•щасФ
тить правильно. О стальны е ж е изначально подразумеваю т, что вы сами,
основы ваясь на пройденном материале, долж ны решить, когда давать свой
Б
ответ (и будет ли он правильны м). Н екоторы е наш и рекомендованные отве­ да *1*0
ты доступны на cairn ' wickedly.sinart.com. . особой
логику ^
они'
Примеры кода максимально упрощены.
Г|0Н^х1&WсЯ-
Н еудобно, если приходится пересматривать 200 строк кода ради тех двух,
которые нуж ны для понимания происходящ его. Ьолы нинство примеров
в этой книге представлены в м аксим ально урезанном виде, чтобы изучаемая
часть бы ла простой и понятной. По этой причине не стоит ж дать от кода
целостности или даж е заверш енности. Т аки м и свойствами будет обладать
ваш код после того, как вы дочитаете книгу. Н аш и примеры создавались
специально для изучения, поэтому они не всегда полноценны. вы здесь ► 27
Техническая редактура: Джессика и Валентин

1 ехждческие редакторы ^Лекугцли. Креюуугцдс


(Vnfentit) Cretidz)
« З аслу га приписы ваю т всем, но за ош ибки всегда о гвечает
автор...» К то-нибудь действительно в это верит? В идите этих
двоих? Если вы найдете в книге технические ош ибки, то, скорее
всего, это га в и н а :)

Д ж е с с и к а Самтг|
ica Sant)

Тсхлсщук.

Валентин Креттас имеет степень м аги ­


стра инф орм ационны х и компью терных наук
Ш вейцарского ф едерального технологического
ДжеСС работает в компании H ew lett-P ack ard института Л озанны (E P F L ). Он работает про­
и вместе со своей командой заним ается само- граммистом в исследовательском институте SR I
восстанавл иваю щ имися сервисами. О на имеет In tern atio n al (М енло-П арк, К али ф орн и я) и з а ­
степень бакалавра университета В иллаповы , нимает долж ность главного инж енера в лабора­
прош ла сертиф икации S C JP 1.4 и S C W C D и на­ тории программного обеспечения при EPFL.
ходится буквально в шаге от получения степени
Валентин — один из основателей и технический
магистра программирования в университете
директор компании C ondris Technologies, спе­
Д рексела (вот так!).
циализирую щ ейся на разработке программного
В свободное время, не занятое работой, уче­ обеспечения.
бой, вязанием крючком (ком у-нибудь нужна
Как исследователь и разработчик он интересует­
ш л яп к а?) и разъездам и на М ини Купере, Д ж есс
ся аспектно ориентированны ми технологиям и,
мож ет отвлечься и поиграть со своей кошкой.
проектировочны ми ш аблонами, веб-сервисами
Родом она и з С олт-Л ейк-С ити, ш тат Ю та (нет,
и архитектурой программного обеспечения. Ва­
она не мормон... только не делайте вид, будто не
лентин увлекается садоводством, лю бит читать
собирались об этом спросить) и сейчас прож и­
и заним аться спортом. Кроме того, он часто мо­
вает недалеко от Ф и ладельф и и вместе со своим
дерирует ф орумы по S C B C D и S C D JW S на с ай ­
муж ем и двум я кошками.
те javaranch.com . О н имеет сертиф икаты SC JP,
Вы можете застать ее за модерированием техн и ­ SC JD , SC B C D , S C W C D и S C D JW S и является
ческих ф орум ов на сайте javaranch.com . соавтором сим улятора прохож дения экзаменов
по SC B C D от компании W hizlabs.
М ы все еще не можем поверить, что он натянул
на себя галстук.
28 введение
Введение

Н еко то р ы е клиди Э ксп ер тн ы е


Другие люЗи, которых можно по ть: рец ензенты ..-
В издательстве O ’Reilly гМЖефср К<дл\Г|с

Выражаем наииысшую признательность Майку Лукидису (M ike


Loukides) из O ’Reilly за то, что он помог оформить серию Head First.
Сейчас, котла к печати готовится второе издание, у нас уже есть
пять книг из этой серии, и все это время Майк был с нами.
Благодарим Тима О’Рейлли (Tim O ’Reilly) за его готовность
пропускать в печать нечто совершенно новое и необыкновенное.
Спасибо талантливому Кайлу Харту (Kyle H art) за подготовку этой
серии. И, наконец, спасибо Эдди Фридману (Edie Freedman) за ди­
зайн обложек для Head First, в которых «акцент сделан на голову*.
Бесстрашные бета-тестеры и рецензенты
Наши высочайшие почтенней благодарность адресованы главе команды
рецензентов Йоханнесу де Йонгу (Johannes dc Jong). Это уже пятая
книга из серии Head First, над которой мы вместе работали, и мы рады,
что ом все еще с нами. Д ж еф ф Кампе (.Jeff Cum ps) неустанно ищет
неточности и некорректные фрагменты уже в третьей нашей книге.
Кори Макглоун (C orey M cGlone). ты крут. Мы считаем, что на форумах
javaranch ты даешь наиболее понятные объяснения. И ты уже, наверное,
заметил, что мы стащили парочку из них. Джейсон Менард (.Jason M e­
nard) неоднократно нас выручал, обращая внимание на технические
детали. Томас Пол (Thom as Paul), как обычно, предоставлял нам
экспертные отзывы и находил тончайшие нестыковки, связанные д ж ей .о О Н .^ П Э
с Java, которые никто другой не смог увидеть. Джейн Гристи (Jane
G riscti), что называется, собаку съела в работе с Java (имея при
этом кос-какое представление и о писательском деле), и нам было
очень приятно получить ее помощь при написании новой книги.
То же самое относится и к давнему участнику форумов javaranch
Барри Гаунту (B arry G aunt).
Мэрилин де Кейруш (M arilyn de Q ueiroz) оказала нам неоценимую
помощь при подготовке обоих изданий этой книги. Крис Джонс
(C hris Jones), Джон Найквист (.John Nytjuist), Джеймс Кубета (James
C ubcta), Терри Кубета (Terri C ubeta) и Айра Беккер (1га Becker)
внесли огромный вклад в создание первого издания.
Особую благодарность выражаем участникам команды, которые были /Азрилин.
qe Keup'JiU
с. нами с самого начала: Анджело Селесте (Angelo Celeste), Микалаю
Зайкину (M ikalai Zaikin) и Томасу Д аф ф у (Thom as Duff) (twduff.com )
И спасибо нашему отличному агенту Дэвиду Роджелбергу (D avid Rogel
berg) из StudioB (а если серьезно, что там с нравами на съемки фильма?)
Крис Джоке

Дздеймс

вы здесь ► 29
Еще больше благодарностей

И когда &ыуже начали думать,


что благодарности закончились*...
Технические эксперты в области Java, которые также выручили нас при подготовке
первого издания (в псевдослучайном порядке):
Э м ико Х ори (E m iko H ori), М ихаэль Т ау п и ц (M ichael T au p itz), М айк Галихью (M ike
G allihugh), М аниш Х атволн (M anish H atw alne), Д ж ейм с Чегуидден (Jam es C hcgw idden),
Ш вета М атур (S h w eta M athur), М охамед М азахим (M oham ed M azahim ), Д ж он Певерд (John
P averd), Д ж озеф Бих (Joseph Bih), С кулрат П атанаванич (S k u lrat P atan av an ich ), Сунил
П алича (S unil Palicha), С уддхазатва Гош (S u d d h asatw a G hosh), Рамки С ринивасан (Ram ki
Srinivasan), А льф ред Роуф (A lfred Raouf), Анджело С елеста (A ngelo C eleste), Д ж он Зутебир
O o h n Z oetebier), Д ж им П ледж ер (Jim Pleger), Б арри Гаунт (B arry G a u n t) и М арк Дьелен
(M ark D ielen).

Команда, создавшая головоломки для первого издания:


Д и к Ш рекм анн (D irk Schreckm ann), М ари «Чемпион по Кроссвордам» Л енерс (М агу
«JavaC ross C ham pion» Leners), Родни Дж. В удроф ф (R odney J. W oodruff), Гэвин Бонг
(G avin B ong) и Д ж ейсон М енард (Jason M enard. Jav aran ch ). У частники ф орум ов Javaranch
благодарны вам за помощь.

Другие соучастники, которых хотелось бы поблагодарить:


Пол Уитон (P aul W h eato n ), участник ф орум ов javaranch, которы й стал проводником в мир
Ja v a д л я ты сяч людей.
Сольвейг Хогленд (Solveig H augland), эксперт в J2 E E и автор книги «D ating D esign P atterns».
П исатели Дори Смит (D ori S m ith) и Том Негрино (T om N egrino) (backupbrain.com ) помогли
нам сориентироваться в мире технической литературы .
Н аш и соучастники по циклу H ead F irst — Э ри к Ф р и м ан (E ric F reem an) и Бэт Ф р и м ан (B eth
F reem an) (авторы книги о ш аблонах проектирования). Благодаря уверенности, которую они
нам внуш или, мы успели закончить эту книгу вовремя.
Шерри Доррис (S herry D orris), спасибо за вещи, которы е действительно имеют значение.

Смелые первопроходгуи, которые одними из первых приступали к чтению книг


серии H ead First:
Д ж о Л и ттон (Joe L itton), Росс П. Голдберг (R oss Р. G oldberg), Д ом иник Д а С илва (D om inic
D a Silva), honestpuck, Д энни Бром берг (D an n y B rom berg), С тивен Л епп (S tep h en Lepp), Э л ­
тон X arc (E lto n H ughes), Э рик К ристенсен (E ric C hristensen), Вулин Н гуен (V u lin h N guyen),
М арк Pay (M ark R au), Abdulhaf, Н атан О ли ф ан т (N ath an O lip h an t), М айкл Брэдли (M ichael
B radly), А лекс Д арроу (Alex D arrow ), М айкл Ф и ш ер (M ichael Fischer), C apa Нотингем
(S arah N ottingham ), Тим А ллен (T im A llen), Боб Томас (B ob T hom as) и М айк Бибби (M ike
B ibby) (первы й).

■Такое огромное количество благодарностей связано с тем, что мы хотим проверить одну теорию. А именно: каждый человек,
упомянутый в книге, купит как минимум один ее экземпляр, а может, и больше (чтобы подарить родственникам и т. д.). Если вы
х о т т е попасть в список благодарностей для нашей следующей книги и у вас большая семья, пишите нам.

30 введение
1 Резкое погружение

О огруу^земся
/ П р и со еди н яй тесь, I-— ■
— ^
водичка отличная!
Вы нырнете глубж е и напиш ете простой
код, а затем ско м п или р уете и запусти те
его. Вы узнаете о си нтаксисе,
ц и клах и ветвлен и ях, рассмотрите
преимущ ества языка J a v a , которые
д е л а ю т его таким популярны м .
М ы научим вас писать код со
\ скоростью света! /

Java О тк р ы в а е т новые ВОЗМОЖНОСТИ. Еще во времена первой (и довольно скромной)


открытой версии 1.02 этот язык покорил разработчиков своим дружественным синтакси­
сом, объектно ориентированной направленностью, управлением памятью и, что важнее
всего, перспективой переносимости на разные платформы. Соблазн написать код один
раз и запускать его везде оказался слишком велик. Однако, по мере того как програм­
мистам приходилось бороться с ошибками, ограничениями и чрезвычайной медлитель­
ностью Java, первоначальный интерес к языку остывал. Но это было давно. Если вы только
сейчас начинаете изучать Java, вам повезло. Вашим предшественникам приходилось
преодолевать целые километры босиком по заснеженным склонам лишь для того, чтобы
заставить работать простой апплет. Однако сегодня в Java гораздо меньше проблем,
работает он быстрее и обладает значительной мощью.

это новая глава > 31


Способы работы Java

Как р а б о т а е т Java
В аш а ц ел ь — н ап и сать пр и л о ж ен и е (в данном
сл у ч а е это и н те р а к ти в н а я си стем а в ы д ачи
п р и гл аш ен и й на в еч ер и н ку) и за ста в и ть е го
р а б о та ть на в сех у стр о й ств а х , к о то р ы е е сть
у ваш и х д р узей .

Исходный код для


интерактивной
системы выдачи
приглашений.

виртуальны е
Ком пилятор
машины
Создайте исходный
О
документ. Используйте
оговоренный протокол
(в нашем случае это
язык Java).
Пропустите документ
через компилятор
исходных кодов.
Компилятор создает
новый документ,
закодированный
о
У ваших друзей
с помощью байт-кода. нет физической
Он проверит код на Любое устройство, Java-машины, но
ошибки и выдаст способное выполнять есть виртуальная
конечный результат Java, сможет (реализованная
только тогда, когда интерпретировать/ программно), которая
будет уверен в его транслировать этот работает внутри
работоспособности файл в такой формат, электронных устройств.
и корректности. который потом Виртуальная машина
получится запустить. считывает и выполняет
Скомпилированный байт-код.
байт-код не зависит
от платформы.

32 глава 1
Резкое погружение

Что &ы будете Желать с Java


В ы со зд а д и те ф ай л с и схо д н ы м ко д о м ,
ско м п и л и р уете е го с пом ощ ью ко м п и л я то р а
ja v a c , а потом за п у сти те п о л ученны й б а й т-к о д
вн утр и в и р т у а л ь н о й м а ш и н ы Ja v a .

I File Edit цлпаиц, Hatp Svaaflr


T^xytjava^wL’; Method PartyO
%java Party
--opartjava.evrt.evCTit.*; 0 aload_0
dass Party {
1 invokeipecial SI <Methodjava.
public void bu'Hdliivttefl { Iang.0b)ect()>
: '3fnef~newFrameO;
4 return
.abel I = oew Labelf'BeuopUHta у Тима");
5<йоп b = now BuitonCBauia ставка*); Method void buildlnvitcO
icfian c = new Button("C6poom»”);
Компилятор 0 new 82<Gass java.awt.Frame>
; :~-dp = newPariei(); виртуальны е
P-ackKI);
О 3 dup

4 irvokespedal S3 <Methodjava.
машины

О
awt.Frame()>
Скомпилируйте файл
Исхос)ник Party.java, запустив
утилиту javac Выполните программу,
(приложение- запустив виртуальную
компилятор). Если все
M od машину Java (Java Virtual
Наберите свой пройдет без ошибок, вы (код) Machine, или JVM)
исходный код. получите еще один файл с файлом Party.dass.

Сохраните его
как Party.java.
с именем Party.dass.
Файл Party.dass,
О JVM транслирует
байт-код в такой формат,
который поймет целевая
сгенерированный Скомпилированный
платформа, и запустит
компилятором, состоит из код: файл Party.dass.
вашу программу.
байт-кода.

~ :: *we4dHue: не ^оспркмилшще Эт^о К4К уЧеёпое г.о-


: : г ^е. Уже совсем скоро вЬь ндЧнетпе писсщЬ К4стпоЯ-
й kg^, <х h°Kct /4л хотцим, Ччг\о$Ы Ол поняли, кзх Этщо
:-с;оттдетп все в/Лесуце.
вы здесь > 33
История Java
S£ Краткая история Java

Классы в стандартной библиотеке Java


3500

3000

2500

2000

1500

1000

500

Java \ .Q V Java 1.1


250 классов.
(versions 1.Z— 1Йг> (versions 1.5 an d u p )
500 классов.
Работает медленно. Работает чуть 2300 классов. 3500 классов.
Забавное имя быстрее. Значительно быстрее. Язык стал мощнее и проще
и логотип. Больше возможностей в разработке.
Может (иногда) соперничать
Интересная и комфортнее для
с машинным кодом. Серьезная, Добавлено более тысячи
в использовании разработчика.
мощная версия. П оставляется в новых классов. Версия
версия. Множество Версия становится тр ех вариантах: Micro Java 5.0 (известная как
ошибок. очень популярной. Edition (J2ME), Standard Tiger) характеризуется
Д остоинство — Edition (J2SE) и Enterprise изменениями в самом язы ке.
Улучшается код для
апплеты. Edition (J2EE). В этот период Он стал более простым
GUI.
Java становится стандартным для программистов
языком для разработки (по крайней мере в теории)
новых промышленных систем и получил новые популярные
(особенно веб-ориентированных) возможности из других
и мобильных приложений. языков.
И зто чи те сбой кзрзийаш Резкое погружение

П о см о тр и те, к зк легко ■at.


Попробуйте угадать, что делает каждая строка этого
п и сать кос) на Java. кода. Ответы вы найдете на следующей странице.

int size = 27; OSbX&WtfcMидлоЧиглькнуа nepe/’i^HjiC c шпеке#. sir* и r.pucwsu&t« ей ^Ч си ие 2 ?■


String name = "*идо";

Dog myDog = new Dog(name, size);

x = size - 5;

if (x < 15) myDog.bark(8);

while (x > 3) {
myDog.play();

int[] numList = (2,4,6,8);

System.out.print("Привет");

System.out.print("Собака: " + name);

String пшп = "8";

int z = Integer.parselnt(num);

try {

readTheFile("myFile.txt");

}
catch(FileNotFoundException ex) {

System, out. print ("Файл не найден.'1) ;

Э то не _
^ глупые Вопросы согласились с ними), поэтому начали рассматривать
Т'1 • Я вижу версии Java 2 и 5.0, но существовали ли разные варианты. Согласно логике следующим
Java 3 и 4? И почему есть Java 5.0, но нет 2.0? должно было стать название Java 3, но применительно
к версии 15 оно еще больше сбивало с толку, поэтому
маркетологи решили присвоить имя Java 5.0, где цифра 5
взята из версии 1.5.
При смене версии с 1.1 на 1.2 изменения в Java
оказались настолько существенными, что маркетологи Итак, изначально платформа имела версии с 1.02 (первый
решили придумать совершенно новое «имя» — Java 2, официальный выпуск) по 1.1 и называлась просто Java.
хотя на самом деле это была версия 1.2. Версии 1.3 и 1.4 Версии 1.2,1.3 и 1.4 принадлежат линейке Java 2. Начиная
тоже относились к линейке Java 2, а 3 или 4 никогда не с версии 1.5, Java называется Java 5.0. Можно встретить
существовали. Анализируя версию 1.5, маркетологи названия Java 5 (без .0) и Tiger (это оригинальное
опять решили, что изменений слишком много кодовое имя). Теперь мы даже не имеем понятия, каких
и понадобится новое имя (и большинство разработчиков сюрпризов следует ожидать от будущей версии...
вы здесь > 35
Почему Java гак популярен

Н аточите с&ой карандаш Q П 1& С И 1 Ы

He переж ивайт е, если пока н е п о н и м а е т е ни о д н о й ст роки


Посмотрите, как лето эт о го кода!
писать кос) из lava. Все, что вы здесь видите, будет подробно описано в книге
(в основном на первых 40 страницах). Если Java похож на язык,
с которым вы работали до этого, то кое-что покажется вам простым.
В противном случае не беспокойтесь — мы все рассмотрим.

int size = 27; 05ь?.!>ЯЯеМцелочисленнуюпеременнуюс именем < гс и присбаибаем ей значение 2 ? .

String паше = "Фидо°; (ЙЬЯблЧем счрзксбуюпеременноюс именемпеп^е и Присвзи&емей значение «Фидо®.

Dog nryDog = new Dog (паше, size) ; Объявляемнсбуо переменнующаух tog с именемчуЪд ипарсдаемей ЦйрамяпрЬ гкяг.е и s'<:«

x = size - 5; fWmr^eM 5 ця 2т (значение size;u псисбаибаем рему/ёщспп переменной х.

if (x < 15) myDog.b a r k (8) ; Еслл х (со ^«чением 2 2 ) менЬиа. Чем1 5 . прия«у1лмемсоЗахе пролаять 3 peg.

while (x > 3) ( |кяполняемцикл поилх ооАше 3.

ncyDog.play () ; ПршмЗЬбаем aoJaxe игралуЬ (Чщо Ь&. Зщо назначило g а? нее).

} Зипопохоже иЛ конец цикла - fee. Чцо «лхоущсЯ внутри скобок [].йало-адецсЯ б циКЛг,

Г.f 7 S 'U '- *' 6 - V & T Ч


int[] numList = (2,4,6,8); ОЗьябляем целлиелмнки; массив nuwust и полйляембкего значения 2.3.6.8-

System.out.print("Привет") ; рлбодим, слобо «TlfK^eiTi1. рерояпуш, б командной с'-ркс-

System.out.print("Собака: " + паше); &s?oguM‘ Прибгап йцуо» (ъ&^сМ&^ыЯ lyrne 'хмеетг значение «Фор») ? командной строке.

String num = "8"; 05Ь*&Лем строковуюпеременнуюпип и присиа -баемей значение “5*.

int z = Integer.parselnt(num); ИреоорцЗуеМецроку «5» б наочоЯЦее Число 8-

5 г Л Й й ’:,.
try ( ТИодемсЯ Чти-ис бЬсполашцЬ- рехможно. >№.о KecJs^oirjeAHjoдолжно р4&лп<П",Ь...

r e a d T h e F i l e ( " m y F i le . t x t " ) ; 'invaeM-irieKcijicfeuj файл с именем пуМеЛл* (или по крайней мере r-йопаемсЯ Зкю сделать).

} Змо Похоже ко Завершение нашей пспЬямси Чпцмщо сделать...

c a t c h ( F ile N o t F o u n d S x c e p t io n e x ) { Здесь ми распознаем. раЗомаютп л» операции, которые Mbt пЦупалиеЬ ёхполниткЬ.

S y s t e m . o u t . p r i n t ("Файл не н а й д е н ." ) ; Если операции завершились неудачей. Йя&хуимб командной строке «Файл не найден».

) Похоже. Что бесЬ код бнутри i J —aiqo наид оейоцбиЯ при с Ь с кдалрЫй моЖ«Н еяр клщьсЯ
бнупюи оператора try.

36 глава ?
Резкое погружение

С труктура кода &Java

Что творится
внутри ИСХОДНОГО
файла

Метод 1 Файл с исходным кодом (с рас­


Выражение ширением .java) содержит опре­
деление одного класса. Класс —
это часть вашей программы;
Метод 2 совсем маленькие приложения
Выражение
Выражение могут обойтись единственным
классом. Содержимое класса
должно находиться внутри пар­
ных фигурных скобок.

Добавляем к л а с с
в исходный файл. Что происходит
внутри класса
Добавляем м е т о д в класс.
Класс может иметь один или
несколько методов. Метод bark
Добавляем выражения из класса D og будет хранить ин­
в метод. струкции о том, каким образом
собака должна лаять. Методы
должны быть объявлены внутри
класса (иными словами, между
его фигурными скобками).

public class Dog {


Что происходит
void bark () {
внутри метода statement!;
Инструкции для метода долж ­
statement2;
ны быть размещены между его
фигурными скобками. Если }
говорить упрощенно, код мето­
да — это набор выражений. Д у ­
майте о методе как о функции Выражения
или процедуре.

вы здесь > 37
Java-клосс

Структура класса
Когда JVM начинает свою работу, она ищет класс, который ей переда­
ли через командную строку. Затем она ищет метод, записанный особым
образом, например так:
public static void main (String[] args) {
// Здесь размещается ваш код
)
Далее JVM выполняет все, что находится между фигурными скобка­
ми {} главного метода. Любая программа на языке Java содержит по
меньшей мере один класс и как минимум один
метод main (один для всего приложения, а не для каждого класса).

^АлиЧнЬШ. -WV4K Ч^ ° ЭкГ|0 K/WCG и О ткр^& оои ^я фигурная


gee Могут иметф fa !), У1МЯ Масса. скобка класса. '
к нему эосттуп. /
аргумент ЗЛЯ Метода.
public class MyFirstApp | Этому методу нужно
\ Тип возвращаемого дередсдтЬ Массив
Это М(л
строками под
отложим на Значения. ЗдесЬ void
говорит о щоМ. Что ничего метода. 5<5анием args. c*o<jL ^ >ОСиАЯ
.\поптом. ^ ~v.
\ во^враЩ/АтЬсЯ ке Зудеть /

public static void main (String[] args)| [{J

System.out.print ("Я управляю")


ЗдесЬ %Ьх)олнЯе.У1\сЯ £te£og
_ £ стан дартн ы й поилок (по умолчание
Щ ч э т о командна* строка). напечатать.
Зачрьгбйкхмая скобка главного

К ^ метода.

Закрывающая ско§ка класса MyFirstApp.

Не п и тай тесь запомнить все Это прямо сейчас.


£ Этой главе вы. лишЬ зе л а е т е свои первЬье шаги.

38 глава 1
Резкое погружение

Создание класса с методом main


В языке Java весь код хранится в виде классов. Вы набираете свой исходный
файл (с расширением .java) и компилируете его в новый файл с байт-кодом
(с расширением .class). Запуская программу, вы на самом деле запускаете класс.
Запустить программу — значит сказать виртуальной машине Java (JVM ):
«Загрузи класс H ello, после чего запусти его метод main ( ) . Продолжай
выполнять, пока не закончится весь код в методе main».
Во второй главе мы подробнее рассмотрим все, что связано с классами, но сейчас
вас должно интересовать следующее: к а к написат ь код н а я зы к е J a va , чтобы он
запустился?
\
Все начинается с метода main(). Именно с него программа приступает
к выполнению.
Неважно, насколько велика ваша программа (то есть неважно, сколько классов
она содержит), всегда должен быть метод пийо(), который приведет в движение
остальной код.

О Сохраняем
M y F ir s tA p p . j a v a

у*'в«'*1ш.ЭтДО|
гЖюсрпПдотП.
I О Компилируем
j a v a c M y F lr s t A p p .j a v a
M yFlrstApp.java

О Запускаем
M tfb d P J rtjfl 'M i d D 1
1’ > 1 Ь Т « !(Ы !Ж
I
in rn w

ttrtto d та й

0 д в ч ш к Я < № d JW A
-------- --------------------------------

M yfirstApp.class

вы здесь ► 39
Выражения циклы ветвление

Что можно разместить


внутри главного метода
Веселье начинается, как только вы переходите
внутрь главного (и ли любого другого) метода. При­
казывая компьютеру выполнить что-либо, можете
пользоваться обы чны ми вы разительны м и средства­
ми, знаком ы м и вам из других язы ков програм м иро­
вания.
В своем коде вы можете сказать JV M следующ ее.

С де ла ть ч т о -'т о
Выражения: объявления, присваивания,
вызовы методов и т. д.

in t х = 3;
S t r i n g name = "Кинжал” ;
х = х * 17;
S y s t e m . o u t . p r i n t ( "х р а в е н п + x );
С а н ты К с и ле с К а е
double d = M ath.random ( ) ;
// Это комментарий
забавы
★ Каждое выражение должно заканчи­
ваться точкой с запятой.
А е л з т ь ч т о - т о снова и снова
х = х + 1 ;
Ц и к л ы : for и while
★ Однострочный комментарий начина­
w hile (х > 12) {
ется двумя слешами.
х = х -1;
) х = 22;
for (int х = 0; X < 10; х = х + 1) {
// Эта с т р о к а м е н я в о л н у е т
S y s t e m . o u t . p r i n t ("Теперь x равен п + х );
} ★ Большинство пробелов, табуляций,
символов переноса строки и т. д. игнори­

о С де ла ть ч т о - т о при условии
Ветвление: условия if/else.
руются.
х = 3 ;

★ Переменные объявляются с помощью


if (х == 10) { имени и типа (в главе 3 вы изучите все
S y s t e m . o u t . p r i n t ( "x должен быть равен 10” ); типы, доступные в языке Java).
) else { int w eight;
S y s t e m . o u t . p r i n t ("x не равен 10”); //Ти п ; in t , имя: w e ig h t
}
★ Классы и методы должны объявляться
if ( (x < 3) & (n am e .e q u als("Кинжал")) ) (
внутри парных фигурных скобок.
S y s t e m .o u t . p r i n t l n ("Осторожно");
p u b lic v o id g o () {
}
/ / Здесь будет
S y s t e m . o u t . p r i n t ("Эта строка выполняется
/ / восхитительный код
в любом с л у ч а е " ) ;
}

40 глава 1
Резкое погружение

Зацикливаем, Простые логические проверки


Вы можете выполнять простые логические
Зацикливаем и... проверки, используя такие операции
сравнения:
В Java есть три стандартные конструкции для
циклов: while, do-while и fo r. Далее мы рассмотрим < (меньше чем);
каждую из них, но пока остановимся на while.
> (больше чем);
Синтаксис (не говоря уже о логике) этого
== (равенство) (здесь два символа).
оператора чрезвычайно прост. Пока некоторое
условие верно, выполняется все, что находится Обратите внимание на разницу между
внутри блока. Этот блок ограничен парными оператором присваивания ( одиночный знак = )
фигурными скобками, поэтому все, что нужно и оператором сравнения (два знака ==).
повторять, должно располагаться именно там. Многие программисты случайно пишут =
Ключевое свойство цикла состоит в проверке вместо “ (но не вы).
условия. В Java проверка условия — это int х = 4; // Присваиваем х значение 4
выражение, которое возвращает булево значение, while (х > 3) {
то есть true либо false. // Код в цикле будет работать, так как
Если вы напишете нечто вроде «Пока мороженое // х больше, чем 3
внут ри упаковки равно true, продолжай копать», х = х - 1;
то получите четкое булево условие. На вопрос, // или цикл будет выполняться вечно
находит ся мороженое в упаковке или нет, }
может быть два однозначных ответа. Но если вы int z = 27; //
напишете «Пока Б об продолжает копать», то не
while (z “ 17) {
получите настоящего условия. Чтобы выражение
// Код цикла не будет запущен, так как
заработало, придется изменить его на что-то
вроде «Пока у Боба насморк...» или «Пока Боб не // z не равно 17
завернулся в плед...». }
вы здесь ► 41
Основы Java
П рим ер ц икла w h i l e
Э то не 0 public class Loopy {
гл у п ы е Вопросы public static void main (String[] args) (
Почему все нужно добавлять int x = 1;
внутрь класса? System.out.println("Перед началом цикла");
while (x < 4) {

О Java — объектно ориентирован­


System.out.println("Внутри цикла");
ный (0 0 ) язык. Это раньше были древние System.out.println("Значение x равно " + x);
компиляторы, для которых вы писали x = x + 1;
монолитные исходные файлы с множест­ )
вом процедур. В главе 2 вы узнаете, что System.out.println("После окончания цикла");
класс — это шаблон для объекта и почти
все в языке Java относится к объектам. }

^>Г}с
ф . Р еду^Ь
Р • Нужно ли добавлять метод main />cjJc ЪфГ}
°*!bi
в каждый класс? % java L o o p y
^ k t
Перед началом цикла

0; Нет. Java-программа может иметь


Внутри цикла

десятки (и даже сотни) классов, но вам Значение х равно 1


нужен только один метод main — тот Внутри цикла
самый, с которого программа начинает Значение х равно 2
работу. При этом у вас могут быть прове­
Внутри цикла
рочные классы с методами main, пред­
назначенные для тестирования других Значение х равно 3
ваших классов. После окончания цикла

ф .
р • В языке программирования,
которым я пользуюсь, разрешено
делать логическую проверку
с целочисленным значением. Можно
-----------ключаыЕмоменты &
Выражения заканчиваются точкой с запятой
ли в Java написать так: Блоки кода задаются парными фигурными скобками { |.
int х — 1; Целочисленная переменная объявляется с типом
while (х){ } и именем: int х;.
Оператор присваивания состоит из одинарного символа: =.
I).
^ • Нет.Типы boolean и integer в языке В операторе сравнения используется два таких символа: ==.
Java несовместимы между собой. По­ Цикл while выполняет все, что находится внутри его блока
скольку результатом проверки условия
(заданного фигурными скобками), пока проверка условия
должно быть булево значение, единст
возвращает значение true.
венная переменная, которую вы можете
проверять напрямую (без использования Если проверка условия вернула false, то блок кода внутри
оператора сравнения), будет иметь тип цикла while не выполнится, a JV M проследует вниз по коду
boolean. Например, вы можете написать: и начнет выполнять выражение, находящееся сразу после
boolean isHot = -true; блока с циклом.
while(isHot) { ) Условие размещается внутри скобок:
w h ile (х = 4) { }

42 глава 1
Резкое погружение
Условное Ветвление
sas
В язы ке Jav a проверка условия с оператором i f ничем не о тл и ­ П ротив
чается от логической проверки в цикле while, но вместо «Пока
у нас все ещ е есть пиво...» мы говорим «Если у нас все еще
есть пиво...» Если вы были внимательны (а мы
class IfTest { в этом не сомневаемся), то должны
были заметить, что мы начали ис­
public static void main (String[] args) {
пользовать println вместо |
int x = 3;
Увидели ли вы разницу?
if (x == 3) {
System.out.println("x должен равняться Зп); System.out.pr/nfm вставляет перенос
строки [print/n расшифровывается
} как printnewiine — «напечатать
System.out.println ("Эта строка выполняется новую строку»), тогда как System.aut;
в любом случае"); print продолжает выводить текст
) в той же строке. Если вы хотите,
} чтобы текст каждый раз печатался
р г в новой строке, используйте println.
Метод print подходит для тех слу­
% java IfTest
чаев, когда текст нужно выводить
х должен равняться 3 в одну строку.
Эта строка выполняется в любом случае

П риведенны й выш е код напечатает «х долж ен равняться 3», Н аточите свой карандаш _
только если соблю дено условие (х равен 3). П редлож ение
«Эта строка вы полняется в лю бом случае» будет выведено
в любом случае. Т аки м образом, в зависим ости от значения Текст, к о т о р ы й нуж но вы ве с т и :
переменной х будет напечатано либо две строки, ли бо одна. % ja v a DooBee
Н о мож но добавить к условию оператор else и получить DooBeeDooBeeDo
возмож ность сказать нечто вроде: «Если у нас еще есть пиво,
пиш ем код дальше, иначе (в ином случае) берем еще нива В п и ш и т е н е д о с т а ю щ и й код:
и только потом продолжаем...»
public class DooBee {
class IfTest2 { public static void main (StringO args) {
public static void main (String[] args) { int x = 1;
int x = 2;
while (x < ______ ) {
if (x = 3) {
System .o u t._________("Doo");
System.out.println("x должен равняться 3");
} else { System, out.___________("Bee");
System.out.println("x не равен 3"); x = x + 1;
} }
System.out.println("Эта строка выполняется в любом if (x ==. H
случае");
System.out.print("Do");
) Но&яЛ р е з у л ь т а т
}
pgSo-vriU программы .

% java IfTest2 v
х не равен 3
Эта строка выполняется в любом случае
вы здесь > 43
Серьезное Java-приложение

Создание серьезного
бизнес-приложения
Т еперь попробуйте собрать воедино все приобретен­
ные сведения и применить их на практике. П онадо­
бится класс с методом m ain(), переменны ми типа
int и String, циклом while и условны м оператором if.
Д обавьте немного лоска — и бизнес-систем а будет
готова. Но, прежде чем посм отреть на код, размещ ен-
ныи на этой странице, подумайте, как бы вы запрог­
рам м ировали детскую песенку про 99 буты лок пива.

public class BeerSong {


public static void main (String [] args)
int beerNum = 99;
String word = "бутылок (бутылки)

while (beerNum > 0 ) {

if (beerNum == 1) {
word = "бутылка"; // В единственном числе. - ОДНА бутылка.
)

System.out.println(beerNum + " " + word + " пива на стене")


System.out.println(beerNum + " " + word + " пива.");
System.out.println("Возьми одну.");
System.out.println("Пусти по кругу.");
beerNum = beerNum - 1;
if (beerNum > 0) {
System.out.println(beerNum + " " + word + " пива на стене")
} else {
System.out.println("Нет бутылок пива на стене");
) / / Конец e l s e
} / / Конец цикла w h ile
} / / Коней м етода m ain
} // Конец класса

В коде есть одна ошибка. Он скомпилируется


и запустится, но результат будет не таким, как
ожидается. Поищите эту ошибку и попробуй­
те ее исправить.

44 глава 1
Резкое погружение

Утро понедельника у Ъ о б а
Буди льн и к зазвонил в 8:30 утра, как и в лю бой другой день недели. Н о у Боба были &H.yyr)pilL
очень насы щ енны е выходные, поэтому он дотян улся до будильника и вы клю чил его.
С этого все и началось — ож ила J a v a -маш ина.

С начала будильник отправил сообщ ение кофеварке*: «Эй, наш чокнуты й опять
уснул, отлож и готовку кофе на 12 минут».

К оф еварка отправила сообщ ение тостеру: «Н е спеш и готовить тосты, Боб еще спит».

Затем будильник передал сообщение сотовому телеф ону Nokia: «П озво­


И jg e c b JdVci.
ни Бобу в 9 часов и скаж и ему, что мы слегка опаздываем».

И, наконец, будильник отправил сообщ ение беспровод­


ному ош ейнику С эм а (С эм — собака) с помощ ью уже
знакомого сигнала, которы й означает «Сходи за газетой,
но не жди, что тебя будут вы гуливать». Ч oUie ,' 6 v ^ e
ecФ
b ^
П ару м инут спустя Боб снова вы клю чил будильник и за­
дремал. Н аконец звонок раздался в третий раз. Но, как только
Боб наж ал спасительную кнопку, будильник отправил собачьему
Р’ ош ейнику сигнал: «Прыгай и лай». Взбудораж енны й и окон­
чательно проснувш ийся Боб поднялся с кровати. Благодаря
изучению язы ка Jav a и удачной поездке на радиоры нок привы чны й режим
ж и зни зам етно улучш ился.
— Э>Т}0 тпостп.
Тост гот ов.
К оф е д ы м и т ся.

Г азет а н а ст оле.

Еще одно чудесное утро в дом е, к о т о р ы м у п р а в л я е т J a v a .

Вы тоже можете иметь такой дом. В оспользуйтесь разумны м реш ением на основе
Java, E th ern e t и технологии Jin i. О стерегайтесь подделок, которы е прим еняю т так
назы ваемую технологию plug and play (что на самом деле означает «включи и мучайся
с этим следую щ ие три дня, пы таясь заставить работать») или «переносимые» п лат­
формы. Бетти, сестра Боба, как-то раз попробовала одну из них, и результат оказался,
как бы помягче сказать, не совсем удовлетворительны м и надежным. Х отя ее собака
гоже отчасти виновата...

Правдива ли эта история? И да и нет. Хотя различные версии Java работают в таких
устройствах, как PDA, мобильные телефоны (особенно мобильные телефоны), пейджеры,
будильники, смарт-карты и т. д. — вы не встретите ее в тостерах или собачьих ошейниках.
Но, даже если вы не находите модель своего любимого устройства с поддержкой Java,
вы все еще можете управлять им через другой интерфейс (например, из ноутбука), на
котором работает Java. Такой подход реализуется с помощью Jini Surrogate Architecture
(сетевая архитектура для создания распределенных систем). Таким образом, вы можете
воплотить в жизнь мечту об /умном» доме.

* IP multicast, если вас интересует конкретный протокол.


вы здесь ¥ 45
Пришло время написать программу

Попробуйте
мой новый генератор
фраз, и вы начнете говорить
так же красиво, как ваш
начальник или парни из отдела
продаж.

public class PhraseCMatic {


public static void main (String[] args) {

il Создайте три набора слов для вы бора Добавляйте собственные слова!


O String[] wordListOne = {"крузшосуточный", "трех-эвенный",
"30000-футовый", "взаимный", "обсадный выигрыш", "фронтэнд",
"на основе веб-технологий", "проникающий", "умный", "шесть
сити", "метод критического пути", "динамичный"};

String[] wordListTwo = ("уполномоченный", "трудный",


"чистый продукт", "ориентированный", "центральный",
"распределенный", "кластеризованный", "фирменный",
"нестандартный ум", "позиционированный", "сетевсй",
"сфокусированный", "использованный с выгодой", "выровненньй",
Хорошо, песенка про пиво — это не сов­ "нацеленный на", "общий", "совместный", "ускореннш");
сем серьезное бизнес-приложение. Вам
все еще нужно что-то более практичное, String!] wordListThree = {"процесс", "пункт разгрузки",
что можно показать начальству? Тогда "выход из положения", "тип структуры", "талант", "подход",
взгляните на код генератора фраз. "уровень завоеванного внимания", "портал", "период времени",
"обзор", "образец", "пункт следования"];

IIВычисляем,сколькословвкаждомсписке
е int onelength = wordListOne.length;
Ре34ИУГ,С
int twoLength = wordListTwo.length;
int threeLength = wordListThree.length;

IIГенерируем три случайных числа


int randl =(int) (Math.random!) * oneLength);
*°чо^е L e S * int rand2 =(int) (Math.random() * twoLength);
int rand3 =(int) (Math.random() * threeLength);
д р а н и ц е , HacwnJ4 ^ Э ч° “

r ,,b'40 О //Теперь строим фразу


String phrase = wordListOne[randl] + " " +
*C1T1
wordListTwo[rand2] + " " + wordListThree[rand3];

IIВыводим фразу на экран


System.out.println("Bce, что нам нужно, - это " + phrase);

46 глава 1 }
Резкое погружение
le n e p a m o p ф р а з

К а к он р а б о т а е т
П рограмма ф орм ирует три списка со словами, потом случайны м образом вы бира­
ет по одному слову из каждого списка и вы водит результат. Н е переж ивайте, если
вам не удалось понять, что происходит в каждой строке, ведь вы только начали
читать книгу. Это лиш ь беглый взгляд с высоты 300 0 0 ф утов на нестандартны й
ум, нацеленны й на образец, использованны й с выгодой.

1 • С начала нуж но создать три строковы х массива — контейнера, которы е будут


хранить все слова. О бъявлять и создавать массивы просто; вот небольш ой п ри ­
мер:
String[] pets = {"Фидо", "Зевс", "Бин"};
Все слова заклю чены в кавы чки (к ак и подобает приличны м строкам ) и разделе­
ны запяты м и.

• Все три списка (м ассива) требую тся для того, чтобы вы бирать из них слу­
чайны е слова, поэтому нужно знать, сколько слов хранится в каж дом списке.
Если в списке содерж ится 14 слов, нам подойдет случайное число между 0 и 13
(нум ерация массивов в Jav a начинается с нуля, поэтому первое слово располо­
ж ено под индексом 0, второе — под индексом 1, а последнее — под индексом 13). Все, что нам
Н ам повезло, так как массив в Ja v a всегда готов сообщ ить о своей длине. Н уж но нужно, —это...
только спросить. И м ея массив pets, мы напишем:
лро*-тшюший
int х = p e t s .length
нацеленный
и переменная х прим ет значение 3.
процесс

взаийшый
СУ • Н ам нуж ны три случайны х числа. Вместе с Jav a поставляется стандартны й
фирменный
пакет с набором математических методов (п ока вы можете дум ать о них как портал
о ф ункц и ях). М етод random () возвращ ает случайное число между 0 и 1 (не
вклю чительно), поэтому мы долж ны умнож ить это число на количество элем ен ­ уполномочены ый
тов (дли ну массива) в нашем списке. Н уж но сделать так, чтобы результат был трехззенный
целочисленны м (дробны е значения недопустимы!); для этого мы используем подход
приведение типов (подробно об этом процессе вы прочтете в главе 4). Это то же
самое, что и преобразование числа с плаваю щ ей точкой в целое число: Круглосуточный
сетевой тип
int х = (int) 24.6;
структуры
А>
I тТеперь нам нуж но построить ф разу, вы бирая но слову из каждого списка динамичный
и склеивая их вместе (не забы вая вставлять между ними пробелы ). Мы исполь­ совместный
зуем оператор +, которы й конкат енирует (и л и просто соединяет) объекты типа обзор
String. Чтобы получить элемент массива, мы даем ему индекс (п ози ци ю ) той
умный
сущ ности, которую хотим использовать: ускоренный
String s = pet s [0]; // s — теперь строка со значением "Фидо" зыход из
з = s + " " + собака"; // s теперь имеет значение "Фидо — собака" положения

3 » Н акон ец мы вы водим фразу в командной строке и... вуаля! Теперь мы в р е ­


кламном бизнесе. вы здесь > 47
Компилятор и JVM

У
Сегодня в эфире: Компилятор
и JV M выясняют, кто из них
важнее

Виртуальная машина Java Компилятор


Привет, я Java! Я тот, кто па самом деле выполняет
программу. Компилятор просто выдает вам файл.
Вы можете распечатать его и наклеить на стену,
сжечь, завернуть в него рыбу и т. д. Но файл
абсолютно бесполезен, пока я его не выполню.
о , Мне неприятен ваш тон.
Вот еще один факт: у компилятора нет чувства
юмора. Конечно, если вам приходится проводить
дни напролет, выискивая мелкие синтаксические
погрешности...

Извините, но если бы не было меня, что бы вы


запускали? К вашему сведению, Java спроекти­
рован для выполнения байт-кода не просто так.
Если бы Java был интерпретатором и транслировал
исходный код на лету, то программы, написанные
на этом языке, работали бы с удручающе низкой
скоростью. Разработчики Java потратили достаточ­
но времени, чтобы убедить людей в том, что скоро­
сти и мощи этого языка хватает для большинства
задач.

Я нс говорю, что вы абсолютно бесполезны.


Но чем же вы на самом деле занимаетесь? Серьез­
но. Я даже не представляю. Программист может
собственноручно написать байт-код, и я его приму.
Вы, должно быть, скоро лишитесь своей работы,
Дружище. Извините, но это абсолютно невежественный
взгляд на вещи (не говоря уже о вашем высокоме­
рии). Если бы это было правдой (теоретически),
то вы смогли бы выполнять любой правильно
сформированный байт-код, даже если бы он не был
продуктом компилятора. На практике это полней­
ший абсурд. Писать байт-код вручную —все равно
что создавать офисные документы, напрямую ис­
пользуя язы к PostScript. И я буду благодарен, если
вы перестанете называть меня «дружище».

К слову, об отсутствии чувства юмора. Вы еще не


ответили на мой вопрос: чем вы занимаетесь на
самом деле?

48 глава 1
Резкое погружение
Виртуальная машина Java Компилятор
Не забывайте, что Java — строго типизирован­
ный язык. Это означает, что я не могу позволить
переменным хранить данные не того типа. Это
чрезвычайно важная особенность для обеспечения
безопасности, и я могу отловить большую часть
ошибок, прежде чем кол дойдет до вас. И я также...
Тем не менее некоторые из них до меня доходят!
Я могу выбросить исключение ClassCastExccption
и иногда замечаю, как люди пытаются добавить
объект одного типа в массив, предназначенный для
хранения совсем другого, и... Извините, но я не закончил. Да, бывают исключи­
тельные ситуации, связанные с типами и возника­
ющие при выполнении программы. Но некоторые
из них должны быть разрешены, чтобы обеспечить
поддержку другой важнейшей особенности Java —
динамического связывания. Во время своей работы
программа может включать в себя новые объекты,
о которых ее разработчик даже не знает, поэтому
я должен обеспечивать некую гибкость. Однако моя
работа заключается в том, чтобы не пропустить код,
который никогда не сможет успешно выполниться.
Как правило, я точно Moiy сказать, когда какой-то
участок кода не будет работать. Например, если
профаммист по ошибке попытается использо­
вать объект Button в качестве сокета для сетевого
соединения, я это увижу и уберегу его программу от
неправильной работы.
Ладно, это понятно. Но что насчет безопасности?
Это же моя прерогатива! А что делаете вы — смо­
трите, правильно ли расставлены точки с запяты ­
ми? Ух, какая серьезная опасность! Как хорошо,
Извините, но я, как говорится, нахожусь на пере­
что у нас есть вы!
довой линии обороны. Описанные ранее ошибки,
связанные с типами, Moiyr привести к разрушитель­
ным последствиям, если их не отловить. Я также
предотвращаю ошибки доступа. Например, код
пытается выполнить приватный метод или из­
менить такой метод, который (по соображениям
безопасности) никогда не должен изменяться. Я не
позволяю людям получить доступ к коду, который
они не должны видеть, и пресекаю попытки извлечь
критически важные данные из другого класса. Мож­
но потратить часы и, возможно, даже дни, чтобы
Как скажете. Но мне приходится делать то же са­ описать важность моей работы.
мое, просто чтобы убедиться, что никто нс схитрил
и не изменил байт-код прямо перед запуском.
Конечно, но, как я уже говорил, если бы мне не
удавалось отловить примерно 99 % всех проблем,
вы бы далеко не уехали. И, похоже, что мы уже
О, можете на меня рассчитывать, друж ище. слишком долго болтаем. Предлагаю вернуться
к этой теме в следующем эфире.
вы здесь » 49
Упражнение: магнитики с кодом

Магнитики с кодом
Части рабочего Java-приложения разбросаны
по всему холодильнику. Можете ли вы сгруп­
пировать фрагменты кода, чтобы итоговая
программа выводила текст, приведенный
ниже? Некоторые фигурные скобки упали на
пол; они настолько маленькие, что их нельзя
поднять. Можете добавлять столько скобок,
сколько понадобится.

?C^jiл ь т з т :

50 глава 1
Упражнение: поработайте компилятором

В
public static void main(String [] args) 1
int x = 5;
while { x > 1 ) {

х = х - 1;
П о р а б о т а й т е К о м п и л ято р о м if ( х < 3) (
System.out.println("маленький икс");
J&XtfbiH, а з J a V a -< j» a £ U o £ на э то й ,
}
CTli.j’aHan.C — ЭТко п о л н о ц е н н ы й

ас*<#наК . 1?aiua з а д а ч а — 1
H fLbrk^ofim bgi К о м и а л я ^ 0?0^
и, с^слшгьь. jScc ли, аз нах
сКомцалар^/ють.с.я. Есла
К ом и адяй й я нс смоЖсть
пройти*,успешно, как £ы
эти» асцраМтье?

A
С
class Exerciselb {
class Exerciselb {
int x = 5;
public static void main(String [] args) (
while ( x > 1 ) {
int x = 1;
x = x - 1;
while ( x < 10 ) (
if ( x < 3) {
if ( x > 3) {
System.out.println("маленький икс");
System.out.println("большой икс");
)
)
)
)
)
}
)

вы здесь ► 51
Кроссворд

Немного разомнем мозга. Это


обычный кроссворд, но почти все
ответы для него взяты из этой главы.
И чтобы вы не теряли бдительность,
мы также добавили несколько
слов, не связанных с Java, которые
относятся к миру высоких технологий.

По вертикали
1. Опять повторить?
2. Хранитель «сущностей». По горизонтали
3. Запускается из командной строки. 10. Какой бывает строка?
4. Числовой тип переменной. 11. Возвращается с пустыми руками.
5. Улаживает проблемы. 12. Набор символов.
6. Загадочный модификатор. 13. Отдел сетевых администраторов.
7. Потребитель исходного кода. 14. Вы просто должны иметь один такой метод.
8. Ее нельзя задать раз и навсегда. 15. Невозможность выбрать два пути сразу.
9. Пока положение не улучшится. 16. Создание нового класса или метода.
17. Проходной двор.
18. Аббревиатура для чипа.

52 глава 1
Смешанные сообщения

Ниже приведен код небольшой программы на языке Java.


Но один ее блок пропал. Ваша задача — найти блоки (слева),
которые выведут соответствующий результат, если их вставить
в код. Не все строки с результатами будут использованы,
а некоторые из них будут задействованы несколько раз.
С м еш анны е Соедините линиями блоки кода и подходящие для них
сообщ ений результаты (ответы можно найти в конце главы).

c la s s T est {
p u b lic s t a t ic v o id m a in (S trin g [] args) {
in t . x = 0 ;
i n t у = 0;
w h ile ( x < 5 ) {
n Jtyythbo

S y ste m .o u t.p r in t ( x + "" + у +" ");


x = x + 1;

Возможные блоки кода: Возможный программный вывод:

у = * - у; 22 46
С ог9^нШ^е
S-ЛСЖ
у *= у * х ;
с ^3 11 34 59

у = у +. 2;
рсз 02 14 26 38
if ( У > 4 ) {
У = У - 1;
} 02 14 36 48

х * х + 1; 00 11 2 1 3 2 4 2
У = У ь х;

11 21 32 42 53
if I У < 5 \ {
х = х т 1;
if ( У < 3 ) { 0 0 11 2 3 3 6 4 1 0
X = X ~ If.
л- * • • U. к - ' . f
} -- 0 2 1 4 2 5 3 6 47
1
J 1 -
У = У + 2;

еы здесь ► 53
Головоломка у бассейна

class PoolPuzzleOne (
public static'void main(String (] args) {
int x = 0;
ГoAojJoAoMKai^Y S&cce&Ha while ( _________ ) {
Ваша задача — взять фрагменты кода со
дна бассейна и заменить ими пропу­
щенные участки программы. Нель­ if ( x < 1 ) {
зя использовать один фрагмент
несколько раз, и не все из них вам
}
пригодятся. Цель — создать класс,
который скомпилируется, запустится
и выведет приведенный ниже текст.
if ( ) {
Не обольщайтесь — это сложнее, чем вы
думаете.

Результат: }
if ( x == 1 ) {
i F ile Edit W ind ow Help C h e at

%java PoolPuzzleO ne
a noise }
if ( ___________ ) (
annoys
an oyster
}
System.out.println;

}
Примечание: каждый
фрагмент из бассейна
может быть использо­
ван только один раз!

System.out.printC'noys");
System.out.print(" "); System.out.printC'oise");
System.out.printC’a "); System.out.printf oyster"),
System.out.printC'n"); System.out.printfannoys");
System,out,printC’an")/
System.out.printCnoise");

54 глава 1
Ответы

H opa6cM t,au> iu К о м ц ш д ять о р о м


class Exerciselb {
0 tbJ5 c « J public static void main(String (] args) {
int x = 1;
while ( x < 10 ) (
x =x +1;
if ( x > 3) 1
М агнит ики с кед о м System.out.println("большой икс");
class Shufflel {
)
public static void main(String [] args)
)
I Э тот код ском пилируется и запустится
int x = 3; ) (без вывода в командной строке),
while (x > 0) { но если не изм енить е го , он будет
работать вечно благодаря бесконечному
if (x > 2) { циклу w hile.
System.out.print("a");
} class Foo {
public static void main(String (] args) {
x = x - 1;
System.out.print("-"); int x = 5;
while ( x > 1 ) {
if (x = 2) { x = x - 1;
System.out.print("b c"); в if ( X < 3) {
} System.out.println("small xn);
I
if (x == 1) {
System.out.print("d"); ) Э тот ф ай л не ском пилируется без
x = x - 1; } объявления класса. И не забывайте
о соответствую щ их ф и гур н ы х
}
скобках!
}
}
}
class Exerciselb (
public static void main(String [] args) {
int x = 5;
while ( x > 1 ] (
x = x - 1;
C if ( X < 3) {
System.out.println("small x");
1
Код из цикла w hile должен
I размещ аться внутри м етода.
) Он не мож ет находиться в самом
классе.

вы здесь ► 55
Ответы
JaVaCrw 7.0
•ц
и 3j
юк о гм а н Н а я
А 6S ®п
Л а
т К
«V
"
о d t е ш
*с р О а п о 7К р
с ,3i t t о е
и О i п м м
Головолом ка у бассейна 15в е т Б Л е н и е с Л е
• ;-ч •| д * . ■
т и н
c la s s P o o lP u z z le O n e {
/ii i 60 б ъ Я в Л е н и е
public static void main(String [] args) {
int x = 0; Д я а ,
ЙЗ it т я

w h ile ( X < 4 ) {
щ» О h

;7Р U ь 1 »i с
System.out. printf'q"); 1. . Г
\ b'J е
if ( x < 1 ) {
System, out. printC ");
}
System.out. printfn" бдаеиганнъге
еооби^ ени#
if ( X > 1 ) {

System, out. printC oyster");


x = x ♦ 2;
}
if ( x == 1 ) {

System.out.prirtC'noys");
>
if ( X < 1 ) {

System.out. printC'oise");
}
S y ste m . o u t. p r in t In ( " " ) ;

X = X ♦ 1;
)

56 глава 1
2 Классы и объекты

Путешествие в Объектвилль
Мы едем
в Объектвилль! ,
Наконец-то мы
покидаем этот
пыльный город
процедур. Я пришлю
вам открытку.

М не ГОВОРИЛИ, ЧТО там будут объекты. В главе 1 вы размещали весь свой


код в методе main(), но это не совсем объектно ориентированный подход. По сути,
он не имеет ничего общего с объектами. Да, вы использовали несколько объектов,
например строковые массивы для генератора фраз, но не создавали свои собственные
типы объектов. Теперь вы оставите позади мир процедур, выберетесь из тесного метода
main() и сами начнете разрабатывать объекты. Вы узнаете, чем же так удобно объектно
ориентированное программирование (ООП) на языке Java, и почувствуете разницу
между классом и объектом. Кроме того, вы убедитесь, что объекты могут сделать вашу
жизнь лучше (по крайней мере ее профессиональную часть; привить вам чувство стиля
мы не можем). Осторожно: попав однажды в Объектвилль, вы уже никогда не сможете
вернуться обратно. Пришлите нам открытку!

з п т новая гяава ► 57
Однажды в Объекгвилле

#ойиз з а кресло,
или Как объекты м огут изменить вашу жизнь
Задание
днажды в магазине программного обеспече­
ния двум разработчикам вручили одно и то
же задание. Надоедливый управляющий
проектами начал подгонять программистов, обе­ буД*1
щая выдать крутое кресло Аегоп (одно из тех, на ■гель0*03 кваДР^ крУ1
Польз0®8, фдгур» СОЛЬВОватвяь
которых сидят все парни из Кремниевой долины) вййИрР® ндк догокна
тому, кто первым закончит работу. Ларри, зани­ треуголь фигуре ов»
елкВ®1 вв S60 DO
мающийся процедурным программированием, ПОдоЫ»
и Брэд, отдающий предпочтение ООП, с энтузи­
азмом восприняли перспективу завладеть столь
лакомым кусочком. формате
Ларри, сидя за компьютером, спросил себя: «Что „даядальв1
именно должна делать эта программа? Какие

ПОД
процедуры мне понадобятся?» И сам тут же
ответил: «ro ta te и p la y Sound*. Таким образом, он
принялся создавать процедуры. В конце концов,
что это за программа, если в ней нет процедур?
Тем временем, сидя в кафе, Брэд лениво зевнул
и спросил себя: «И з чего состоит эта программа?
Какие ее ключевые компонент ы?» Сначала он
подумал о фигурах. Конечно, он помнил и о дру­
гих объектах, таких как пользователь, звук и событие
нажатия. Н о у него уже была библиотека для этих частей
программы, поэтому он сосредоточился на создании
фигур. Посмотрите, как Брэд и Ларри реализовали свои
программы, и попытайтесь догадаться, кто ж е вы и грал
Аегоп.

Из рабочем месте Ларри $ кафе, тде находится ^рэд


Как и много раз до этого, Ларри сосредоточился с ноутбуком
на написании своих важных процедур. Брэд написал к л а ссы для каждой из трех фигур:
В мгновение ока он создал две процедуры: Sq u are
rotate и playSound.
rotated { C ir c le |
rotate (shapaNurn) { // Код для араще
// Поворачиваем фигуру на 360° // каадрата rotate(){ T rian g le
} > // Код для вращвь
playSound(shapeNum) { playSoundf) { ) rotated {
// Используем переменную shapeNum //Код для вослро playSoundd! //Коддля вращения
/ / для определения того, некой звуковой файл //файла AIF. кою // Код для Bocnpoi // треугольника
//для квадрата //файла AIF. k o t o j }
// нужно воспроизвести, и воспроизводим его
} //для круга playSounddl
) } // Код для воспроизведения
// файла A1F, который задан
// для треугольника
)

58 глава 2
Л а р р и уж е с ч и та л себя победителем и п о ч ти ошушзл Классы и объекты
ста льн ое основание нового кресла...
П о с т о й те ! Задание изменилось.
«Ладно, Ларри, формально ты был первым, — сказал управляющий, — но необходимо добавить
в программу небольшую деталь. Для таких первоклассных программистов, как вы оба, это не соста­
вит труда».
«Ох, если бы мне давали монетку каждый раз, когда я слышу нечто подобное, — подумал Ларри, пре­
красно понимая, что изменение в задании, не вызывающее никаких проблем, — это фантастика. —
Да и Брэд выглядит каким-то подозрительно спокойным. К чему бы это?»
Ларри все еще верил, что объектно ориентированный подход хоть и интересный, но слишком гро­
моздкий. В этом он был абсолютно убежден и не собирался менять свою позицию.

Ларри вернулся на рабочее место Агв ато время ^рас) на пляже...


Процедура для вращения фигур по-прежнему Брэд улыбнулся, хлебнул немного коктейля
должна работать; в коде используется таблица и написал новый класс. В такие моменты в ООП
для нахождения графической фигуры, на кото­ ему больше всего нравилось то обстоятельство,
рую указывает переменная shapeNum. Но про­ что не нужно трогать код, который уже был
цедуру p la y S o u n d придет ся изменить. И что протестирован. «Гибкость, расширяемость», —
это за файл в формате HIF? приговаривал он, размышляя о достоинствах
playSound(shapeNum) { ООП. ______________________ ,
// если фигура — не амеба, Amoeba

// какой AIF-файл нужно проигрывать, rotated {


// и воспроизводим его И Код для вращения амебы
// иначе }
// воспроизводим файл HIF для амебы playSound!) {
> И Код для воспроизведения
Повернуть фигуру не сложно, но и з-за // HIF файла,
необходим ост и т рогат ь р а н ее проверенны й // предназначенного
код Ларри становится плохо. Уж он-то II для амебы

должен был знать, что, несмотря на заверения


управляющего проектами, задан и е всегд а
м еняет ся. вы здесь ► 59
Однажды в Объектвияле

Л з р р ц успел опередить ЬрэЪа лишь на секунду.


«Ха-ха! Куда там нелепому ООП». Но улыбка на лице Ларри быстро растаяла, как только
надоедливый управляющий проектами сказал (с нотками разочарования в голосе): «О нет,
амеба должна вращаться совсем не так...»
Чуть ранее оба программиста использовали следующий алгоритм для вращения.
1 . Определить прямоугольник, который вмещает в себя фигуру.
2. Вычислить центр прямоугольника и повернуть фигуру вокруг этой точки.
Но амебоподобная фигура должна вращаться вокруг точки на ее конце, как стрелка в часах.
«Все, я готов, — подумал Ларри, представляя себя в виде обуглившейся гренки. — Хотя
я могу добавить еще одно условие if/else в процедуру для вращения и затем написать код
специально для амебы. Думаю, из-за этого ничего не сломается». Но тоненький голосок
где-то у него внутри прошептал: «Наивный. Неужели ты действительно думаешь, что
задание больше не будет меняться?»

0 S это м 6 задании
деликатно умалчи&алось.

#ернувшись на рабочее место, 1ем временем Ь у э д ,


Ларри... лежа с ноутбуком из раскладушке
...решил, что лучше добавить аргумент для на фестивале народной мрыки
точки вращения в соответствующую про­ в1еллерзйде...
цедуру. П ридет ся изменить м ного кода.
Тестирование, перекомпиляция — все это ...ни капли не сомневаясь, отредактировал метод
придется делать заново. Части кода, которые rotate, но только в классе Amoeba. Он никогда
работали ранее, больше не работают. не трогал проверенный, работающий и скомпи­
лированный код, который относится к другим
rotate(shapeNum, xPt, yPt) {
// Если фигура — не амеба,
частям программы. Чтобы задать точку вращения
// вычисляем центральную точку, для амебы, Брэд добавил Amoeba
// основываясь на прямоугольнике, атрибут, который должен intxPoinl
// затем вращаем быть обязательным для всех int yPoint
/ / иначе амеб. Он изменил, проверил
rn(ate<)<
// Код для вращения амебы
// используем xPt и yPt // с использованием ее
// как сдвиг для точки вращения и отправил по W i-Fi итого­ // координат
/ / и затем вращаем вую программу быстрее, чем
playSound(H
успела доиграть одна-единст II Код для воспроизведения
II нового HIF файла для амебы
венная композиция. !
60 глава 2
Классы и объекты

Итзк, кресло получилЬ рэс), отдзюший


предпочтение ОиГТ, прз&ильно?
Н е спешите. Ларри нашел недостаток в коде Брэда.
И, поскольку он был уверен, что благодаря новому
креслу сможет произвести впечатление па симпатичную
бухгалтершу, то решил указать на этот недостаток.
Ларри: Ты дублируешь код! Процедура rotate
находится во всех четырех штуковинах.
Брэд: Это м ет од, а не процедура. И он находится
в классах, а не «штуковинах».
Ларри: Какая разница? Это глупый подход. Ты должен
поддерживать четыре разных метода rotate. Что в этом
может быть хорошего?
благодаря креслу Ларри надеялся
Брэд: Похоже, ты не видел конечный результат. Давай произвести на нее впечатление
я покажу тебе, как в ООП работает наследование.

Square

rotale()
Circle

rotate!) £
Triangle

rotate!)
i
Amoeba

rotate!)
О
Я выяснил, ч то общего
playSoundQ playSound() playSound() playSoundQ между всеми этими
классами.
’ J-J

© О
Это фигуры, которы е
З а тем я связал
вр ащ аю тся и воспроизводят
остальные четы ре
Звуки. Я абстрагировал их общие
класса с новым
черты и поместил в новый класс
классом Shape,
с именем Shape.
используя отношения
под названием
Можете читать это как «квадрат унаследован
от фигуры», «круг унаследован от фигуры» «наследование^.
Родительский класс
и т. д. Я убрал методы rotate!) и playSound() из
других фигур, поэтому теперь нужно поддержи­
вать всего один экземпляр каждого из них. Дочерние классы
Класс Shape родительский для остальных
четырех классов, которые, в свою очередь, Square Circle Triangle Amoeba
являются дочерними (потомками, или подклас­
сами) для Shape. Дочерние классы наследуют
методы родительского класса. Иными словами,
если класс Shape обладает какой-то функцио­ 1
нальностью, то его подклассы получают те же ' 1
возможности.
вы здесь * 61
Однажды в Объектвилле

к как быть с методом rotateдля фитуры A m oeba?


Ларри: Не кроется ли вся проблема в том, что амеба имеет совершенно
другие процедуры rotate и playSound?
Брэд: Методы!
Ларри: Не имеет значения. Как же амеба сможет делать что-
то по-своему, если она наследует свою функциональность от
класса Shape?
Брэд: Класс Amoeba переопределяет методы класса Shape.
При выполнении программы JV M будет точно знать, какой именно
метод rotate нужно вызвать, когда придется вращать амебу.
О
Я сделал т а к , чтобы класс
Родительский класс Amoeba переопределил
(а б с тр а к тн ы й ) методы rotateO и playSound О ,
принадлежащие родительскому
классу Shape.

Дочерние классы Переопределение означает, ч то


(конкретны е) подкласс заново описывает
унаследованные им методы,
если ему нужно изменить или
Square Circle Triangle
расш ирить их поведение
f.
Vt rotate() {
U amoeba-specific
И rotate code ) Переопределение
методов
p lay S o u n d () {
II amoeba-specific
// sound code }

Я могу
, сама о себе
Ларри: Как ты указываешь амебе сделать позаботиться.
Я знаю, как амеба
что-нибудь? Вызываешь ли ты при этом ^должна вращаться
процедуру, прости, — метод, и говоришь и воспроизводить
ему, какую именно фигуру нужно вращать? звуки.

Брэд: Именно за это я люблю ООП. Когда


нужно повернуть, например, треугольник, Я знаю, как должна
в коде вызывается метод rotate() из объекта вести себя фигура. Тебе
лишь нужно сказать, что
Triangle. Остальная часть программы даже мне делать, а я уже выполню всю
не знает о том, как треугольник это делает работу. Не забивай свою голову
(и ей все равно). Если же нужно добавить деталями о том, как я буду это
в программу что-то новое, ты просто делать.
создаешь новый класс для нового типа
объектов, которые будут вести себя по-
своему.

62 глава 2
Классы и объекты

Яумираю от любопытства!
Кто получил кресло^

Э ми со второго этажа.
Д ерж а все в тайне, управляю щ ий
трем

у^ £и л а
мозга
Пора размять извилины
Вы только что прочли историю о том, как
Что вам нравится в 00Л£ поклонник процедур встретился лицом к лицу
с программистом, предпочитающим ООП.
Вы получили общее представление о таких
«О но пом огает мне разрабатывать программы объектно ориентированных концепциях,
более естественны м путем . П редм еты им ею т как классы, методы и атрибуты. Оставшуюся
возможность развиваться». часть главы мы потратим на изучение классов
Джой, 27 лет, архитектор программного обеспечения и объектов (а в следующих главах вернемся
к наследованию и переопределению).
« Е с л и нужно добавить новую ф ункциональность, Исходя из того, что вы только что увидели
мне не пр ихо дится возвращаться к коду, (а также узнали из других объектно
которы й я уже протестировал». ориентированных языков, с которыми
Брэд, 32 года, программист
работали раньше), уделите несколько минут
следующим вопросам.
«М не нравится, что данные и м ето д ы , которые
этим и данны ми оперирую т, находятся в одном О каких фундаментальных вещах вы обязаны
кл ассе». помнить, проектируя класс на языке Java?
Джош, 22 года, любитель пива О чем вы должны себя спросить? Что
бы вы внесли в список, который должен
«П р и влекает возможность повторного использоваться при проектировании класса?
использования кода в др уги х прилож ениях.
Создавая новый кл а сс, я м огу сделать его
достаточно гибким , чтобы потом применять
в сво и х проектах». О б в д о з н а М ^ ъ с л ь н ы й c o jk tb
Крис, 39 лет, руководитель проектов Если при решении упражнения
вы зашли в тупик, попробуйте
«Н е м о гу поверить, что Крис м о г сказать такое.
поговорить о нем вслух.
За последние 5 л е т он Не написал ни строчки
кода». Во время разговора активи­
Дэрил, 44 года, работает на Криса зируются различные участки
мозга. Хотя лучш е всего
«П о м и м о кресла?» это работает при общении
Эми, 34 года, программист с другим человеком, домашние животные тоже
подойдут. Именно так наша собака изучила
полиморфизм.

вы здесь » 63
Думайте об объектах

Проектируя класс, думайте о б объектах, которые


£удут созданы на его основе. Думайте:
■ о вещах, которые объект зн а е т;
■ вещах, которые объект д е л а е т.

ShoppingCart * Button Alarm

label • aiarmTime
cartContents Знает color Знает alarmMode Знает
;
setColor() setAlarmTime()
addToCart() Делает setLabelQ Делает getAlarmTimeO Делает
removeFromCartO dePressQ isAlarmSetO
checkOut() 1 un Depress() snooze()
1

'То, ч т о о б ъ е к т о се^е знает, н азы вается


■ переменной экземпляра. Переменные
экземпляра
(состояние ) 1

Го, ч т о о б ъ е к т м о ж е т д е л а т ь , н а зы в ается
Методы
(поведение)
■ методом.

Вещи, которы е объект о себе знает, назы ваю тся Н аточите свой карандаш
переменными экземпляра. О ни отраж аю т состояние
объекта (дан ны е) и могут иметь уникальны е зн аче­
ния д л я каждого объекта выбранного типа. Напишите, о чем должен знать
и что должен уметь объект
Думайте об экземпляре класса как о синониме слова Television.
объект.
Методы — это действия, которые объект спосо­
бен вы п о лн я т ь. П роектируя класс, нуж но думать
о данных, которы е долж ен знать объект. Кроме Переменные
того, необходимо создавать методы, которы е будут экземпляра
работать с этим и данны ми. Ч асто объекты содерж ат
методы д л я чтения и записи значений, относящ ихся
к переменны м экзем пляра. Н апример, объект Alarm
вклю чает в себя переменную экзем п ляра для хране­ Методы
ния времени срабаты вания (aiarm T im e) и два метода
д л я ч тен и я/зап и си значений этой переменной.
И так, у объектов есть переменные экзем п ляра и м е­
тоды, но эти сущ ности создаются как часть класса.

64 глава 2
Классы и объекты

В чем разница между


классом и о б ъ ек та ?

Класс это не объект.


Класс —это шаблон для объекта.
О н говорит виртуальной маш ине, как
сделать объект заданного типа. Каж дый
объект, созданны й из этого класса,
м ож ет иметь собственны е значения
дл я переменны х экзем п ляра класса.
Н априм ер, вы мож ете использовать К/кДсс
класс B u tto n для получения множ ества
различны х кнопок, и каж дая из них будет
иметь свои цвет, размер, ф орму, метку и т. д.

С м о г ш и м и H3L ЭНьО Т Ы К : Объект — это что-то вроде одной записи


в телефонной книге.
Еще одной аналогией для объектов может служить
набор чистых карточек Rolodex. Они имеют одни и те же
пустые поля (как и переменные экземпляра у объекта).
Когда вы заполняете карточку, вы создаете экземпляр
объекта, а записи на карточке описывают его состояние.
Методы класса — это действия, которые вы выполняете
с конкретной карточкой. Например, getName()f
changeNameO, setNameO могут быть методами класса
Rolodex.
Итак, все карточки могут делать одни и те же вещи
(getName(), changeNameO и т. д.), но каждая из них
обладает уникальной информацией.

вы здесь > 65
Создание объектов

Создаем первый объект


Итак, что необходимо для создания и использования объекта? Вам
понадобятся два класса. Один класс нужен для описания типа приме­ Оператор доступа
няемого объекта (D og, AlarmClock, Television и т. д.), другой — для т е­ «то ч к а » ( .)
ст ирования нового класса. Проверочный класс содержит метод main(),
в котором вы создаете объекты нового типа и получаете к ним доступ. Этот оператор предостав­
Этот класс позволяет опробовать методы и переменные экземпляра ляет доступ к состоянию
объекта и его поведению
объекта, созданного из вашего нового класса.
(к переменным экземпля­
Далее в наших примерах вы неоднократно встретитесь с такими ра и методам).
парными классами. Один класс будет наст оящ им — из него мы будем
создавать объекты для последующего использования, а другой будет
И •:<з-дзел; коаый объект
проверочным и носить название <ИмяВашегоПервогоКласса>
T e s t D r i v e . Например, если мы создали класс B u n g e e, то тестовый Dog d = new Dog();
класс будет называться B u n g e e T e s t D r iv e . Класс с именем
< И м яВ аш егоП ервогоК ласса> Т ез£В г 1 \г е будет содержать метод
ii Вакназшайм ащ щщт гояос,
main(), и его единственная цель будет заключаться в создании объ­
ектов вашего нового типа (не проверочного класса) и доступе к его И аопуаш цасгуп ц г&етоду barky
методам и переменным экземпляра через оператор доступа «точка» (.). U ч*р*г «перлтор «гочх*»
Все это будет подробно рассмотрено на следующих примерах. d.bark();

О Создаем класс.
". - ■его
class Dog { U ’к-рэтордодтузэ
DOG
^ ер*МеннЫъ d .s iz e = 4 0 ;
int size; size
String breed; breed
name
String name;
bark()

о
void bark() {
System, out.println("Гав! Гав!");
Создаем проверочный класс (T estD rive).

ТлйЙиЬ Л /*™ °Э class DogTestDrive {


public static void main (String[] args) {
// Проверочный код для класса Dog
)
в не&о *°ЭК }
Создаем внутри тестового класса объект и получаем доступ
© к его переменным экземпляра и методам.
class DogTestDrive {
public static void main (String[] args) {
D o g d = new D o g () ; . Co
d .size = Если у вас уже сложилось
= 40; ^ c c g Ooa определенное представление
qogW ^ ^ 4 . bark об ОТТГТ, вы должны
<c-K\0 (); ч Vc^ & Je 2 ° l Z c^ a- были заметить, что в этом
примере не используется
} $*3(явйем м ел ю з i a r k d ^ П0Л* Size' инкапсуляция. Эту тему мы
рассмотрим в главе А.
66 глава 2
Классы и объекты

Создание и тестирование объектов Movie


class Movie {
String title;
String genre;
int rating;
void playlt() {
System.out.printin("Проигрывание фильма");
}
)
public class MovieTestDrive {
public static void main(String[] args) {
Movie one = new M o v i e ();
one.title = "Как Прогореть на Акциях";
one.genre = "Трагедия";
one.rating = -2;
Movie two = new M o v i e ();
two.title = "Потерянные в Офисе";
two.genre = "Комедия";
two.rating = 5 ;
two.playIt();
Movie three — new M o v i e ();
three.title — "Байт-Клуб";
three.genre = "Трагедия, но в целом веселая";
three.rating = 127;
)
)

Нзточшпе свой караиба ы

■*4

object 1 genre

у rating
J
title

Класс MovieTestDrive создает объекты (экземпляры) object 2 genre


класса Movie и с помощью оператора доступа (.)
присваивает определенные значения его переменным
экземпляра. Он также вызывает методы этих объектов.
rating
J
Справа показана схема. Заполните ее значениями из г title
трех объектов, полученными к концу метода main().
object 3 genre

V,
rating
J
вы здесь > 67
Выйти на свободу из main

Скорее! выбирайтесь из гла&иого метода!


Будучи в методе main(), вы все еще находитесь за пределами Объектвилля. Хранить весь код в глав­
ном методе — это нормально для тестовой программы, но при создании настоящих объектно ориен­
тированных приложений ваши объекты должны будут общаться с другими объектами. Создавать
и тестировать их внутри статического метода m ain() — не самая лучшая идея.

А & з в а р и а н та применения м етода main:


■ тестирование настоящего класса;
■ запуск/старт Java-приложения.
Настоящее приложение на языке Java целиком состоит из объектов, общающихся между собой.
Общение в данном случае означает, что объекты вызывают методы друг друга. На предыдущей стра­
нице, а также в главе 4 применение метода m ain() рассматривается в контексте отдельного класса
TestD rive с целью создания и тестирования методов и переменных экземпляра другого класса.
В главе б мы рассмотрим вариант использования класса с главным методом для запуска настоящего
Java-приложения (создавая объекты и давая им возможность взаимодействовать друг с другом).
В следующем примере мы попытаемся показать, как может вести
себя настоящее приложение на языке Java. Находясь на ранней
стадии изучения Java, мы используем небольшое количество ин­
струментов. По этой причине приложение покажется вам немного
нескладным и неэффективным. Вероятно, вам захочется улучшить
его, и именно этим мы займемся в следующих главах. Не волнуй­
тесь, если какие-то части кода останутся для вас непонятными;
смысл примера — показать, как объекты общаются между собой.

И гр а в угадывание
Краткое описание
Игра предусматривает один игровой объект и три объекта-игрока. Гене­
рируются случайные числа от 0 до 9, а три объекта-игрока пытаются их
угадать (мы и не обещали, что это будет захватывающая игра).

Классы
GuessGame.class Player.class GameLauncher.class

Логика
1. Класс GameLauncher — это точка, из которой стартует приложение;
он содержит метод main().
2. В методе main() создается объект GuessGame, из которого вызывает­
ся метод startGameQ.
3. В методе startGameO объекта GuessGame происходит весь игровой
процесс. Он создает трех игроков, затем «придумывает» случайные
числа (которые игроки должны угадывать). После того как каждо­
го из игроков просят угадать число, проверяется результат и либо
выводится информация о победителях, либо игроков просят угадать
еще раз.
68 гла ва 2
Классы и объекты

public class G uessG am e {


Player p i ;
Player p 2 ; ^ Пере/леннЬи
Player p3;
er.
public void startGameO {
pi = new Player<);
p2 = new Player(); Создаем v\pu о$Ъеюп<а ? ty e r u Присваиваем ux
p3 = new Player(); ■Y^peM переМеннЫУА ЭК<Зе МГ|>ПЯра.
int guesspl — 0;
int gue isp2 = 0;
int guessp3 = 0; « ' ^ У Дкаждого
Г игрока
Г ’- -
boolean plisRight = false
boolean p2isRight = false ; Объявляем три переменнее для хранения пра&лЬностпи
boolean p3isRight = false ; или непр^и^ностпи (true или fa ke ') оптт|(?етт|о
п & й$ игрок^.
игроков.
int targetNumber = (int) (Math.random() * 10) ; Создаем Число,
System, out .prin tin ("Я загадьтяв число от 0 до 9..."); к о то р о е uzj>o^u
while(true) ( должны, угадауг\Ь.
System.out.printin("Число, которое нужно угадать, — + targetNumber);

pi.guess ();
р 2 .guess (); $Ь$Ыёаемме-щод guess 0 U3 каждого
р Э .guess();

guesspl = p i .number;
System, out .pr in tin ("Первый отрок думает, что это guesspl) ; \ И з ^ К а е / А &риОКУГ)Ь1
) каждого игрока
guessp2 = р2.number; / г ~ , I ^
System, out .print In ("Второй игрок думает, что это " + uessp2) , 1 pdOO*Yr)bl
I их Merrioyob cjuessO),
guessp3 = рЗ.number;
System, out. print In ("Третий игрок думает, что это \ ПолуЧаядоступ к ux
^Перемекн£ям дитцЬег.
if (guesspl = targetNumber) { V П роверяем ^apuaKYnbt каж д о го u j игроков
plisRight = true;
/
Н4 соо7Г)£е-уцс7Г|£ие загаданному Числу.
}
if (guessp2 = targetNumber) { Если игрок угадал, тпо присваиваем
{
p2isRight = true; (
С00>п(>е>пс>пъу}0Цей Переменной значение
}
if (guessp3 = targetNumber) { j
true (помкитгпе. Чкт]0 по умолчанию она
p3isRight = true; храни-щ значение false).
)
} ^ Если пер&ш игрок, ИЛИОпорой игрок,
if (plisRight || p2isRight I| p3isRight) ( ИЛИ’гг)рв>т)ий игрок у гс ^ а л (оператор Ц
означает} ИЛИ)М. Г Г
System, out. printin ("У нас есть победитель!");
System, out. print In ("Первый игрок угадал?" + plisRight);
System.out.printin("Второй игрок угадал?" + p2isRight);
System, out .printin ("Третий игрок угадал?" + p3isRight) ;
Sys tem.o u t .println ("Конец игры.") ;
break; // Игра о.кончена, так ч *£о гдохя

) else { , ^ °суг)^емся ЙI
if дсзджгач t ieh как з»»«гео :wt ул'^^Дл!
System, out. print In ("Игроки должны попробовать еще pas
} // х.<>у?ец if/else ^ У*Ц
} /7 хет& ц дел«к&
) // эддесм
) / / ксяе” класса
вы здесь > 69
Игра на угадывание

Запускаем нашу игру


public class Player {
int number = 0 ; II Здесь хранится вариант числа
public void guess () { Программный вывод (будет отличаться
от запуска к запуску)
number = (int) (Math.random() * 10);
I Fite Edil Window Help Explode |
S y s t e m . o u t . p r i n t l n ("Думаю, это число " + number); .А .И '»
%java. i
S ameLauncher
)
Я Загадываю число о® 0 до 9...
)
public class GameLauncher ( Число которое нужно у г а д а т ь , - 7

public static void main (String[] args) { Думаю, это число 1

GuessGame game = new GuessGame(); Думаю, это число 9

game.startGame(); Д у м а ю , это число 9

> Первый игрок думает, что это 1


Второй игрок думает, что это 9
Третий игрок д у м а е т . что ЭТО 9
Java выносит мусор Игроки должны попробовать еще раз
Ч и с л о , которое нужно угадать, - 7
Каждый раз, когда в Java
создается объект, он отправ­ Д у м а ю , это число 3
ляется в область памяти под Д у м а ю , это число 0
^званием куча (heap). Все Думаю, это число 9
объекты, независимо от того,
Первый игрок думает, ЧТО ЭТО 3
когда, где или как они были созданы,
расположены в куче. Но это не просто Второй игрок д у м а е т , что это Q
классическая куча в памяти — в Java Третий игрок думает, что это 9
она управляется сборщиком мусора. Игроки должны попробовать эщз раз
Когда вы создаете объект, Java выделя­
Ч и с л о , которое нужно угад а т ь , - 7
ет участок памяти в куче такого разме
ра, который необходим этому объекту. Думаю, это число 7
Например, объект с 15 переменными Думаю, это число 5
экземпляра, вероятно, потребует Д у м а ю , это число 0
больше места, чем объект с двумя пере
Первый игрок думает, что это 7
менными. Но что происходит, когда вам
нужно освободить это пространство? Второй игрок д у м а е т , что это 5

Каким образом можно убрать объект Третий игрок д у м а е т , что это 0


из кучи после того, как он больше не У нас есть победитель!
нужен? Java сделает это за вас!
Когда JVM видит, что объект больше Первый игрок угадал? true
не понадобится, она делает его пригод­
ным для сборки мусора. И если у вас
заканчивается память, сборщик мусора
запускается, выбрасывает недоступные
объекты и освобождает место, что­
бы вы снова могли его использовать.
В следующих главах вы больше узнаете
об этом процессе.

70 глава 2
Э то не 0 Классы и объекты
глупые вопросы
'аРОМ^ТРи
ф .
Р • А вдруг мне понадо­ ф Что представляет собой
_ п*реаастся
бятся глобальные перемен­ программа на языке Java? Что
ные и методы? Как я смогу мы получаемна выходе?
реализовать их, если все
должно храниться в клас­
сах? о •■ Java-программа — это
набор классов (где есть хотя
бы один класс). В приложе­
0;• В объектно ориентиро­ нии на языке Java один класс
ванных программах на языке должен содержать главный
Java нет понятия глобаль­ метод, который используется
ных переменных и методов. для запуска программы. Как
Однако иногда нужно, чтобы программист вы создаете
какие-то методы или констан­ один или несколько клас­
ты были доступны в любой сов, которые и будут про­
части программы. Вспомни­ дуктом вашего труда. Если
те о методе random ( ) из у конечного пользователя нет
приложения для генериро­ JVM, вам придется добавить ее
вания фраз; он должен быть в свое приложение, чтобы запу­
доступен везде. А как насчет стить его. Существует несколько
такой константы, как число установщиков, которые позво­
ляют упаковывать классы вместе
КЛЮЧЕВЬЕ МОМЕНТЫ
пи? В главе 10 вы узнаете,
что ключевые слова public с различными версиями JVM Объектно ориентированное программи­
и static делают метод (например, для разных платформ) рование позволяет расширять при­
почти глобальным. Вы можете и размещать все это на компакт­ ложение, не затрагивая проверенный
вызывать публичные стати­ диске. Таким образом, конечный ранее и работающий код.
ческие методы из любого пользователь сможет установить Весь код в Java находится внутри
кода, из любого класса своей корректную версию JVM (конечно, к л а ссо в .
программы. А пометив поле если он этого еще не сделал).
Класс описывает, как создавать объект
как public, static и final, определенного типа. К л а с с — это что-
вы получите глобальную
константу. ф; А если у меня есть сто
то вроде ш аблона.
Объект может сам о себе позаботиться;
классов? Или тысяча? Разве
вам не нужно знать, как именно он это
удобно поставлять столько
ф; Как это связано отдельных файлов? Могу ли
делает.
Объект кое-что з н а е т и у м е е т делать.
с ООП, если вы все равно мо­ я упаковать их в единственный
Сведения об объекте называются пере­
жете создавать глобальные исполняемыйфайл1 м енны м и экзем п л яр а. Они определяют
функции и данные?•
состояние объекта.
0; • Да, поставлять столько
Действия объекта называются м е то ­
6;• Прежде всего все в язы­ отдельных файлов конечному
дам и. Они обуславливают поведение
объекта.
ке Java разбито по классам. пользователю очень неудобно, но
Для каждого класса можно предусмо
Число пи и метод random (), вам и не придется этого делать.
треть отдельный проверочный класс,
несмотря на ключевые слова Вы можете упаковать все свои который будет использоваться для
public и static, объявле­ программные файлы в единый
создания объектов нового класса.
ны внутри класса Math. И вы Java-архив — файлJAR, который
Класс может н а сл е д о в а ть поля и ме­
должны помнить, что эти основывается на формате PKZIP.
тоды от более абстрактного родитель­
статические (как бы глобаль­ В такой архив вы можете добавить
ско го к л а с с а .
ные) сущности считаются для простой текстовый файл, отфор­
Работающая программа на языке
Java скорее исключением, матированный в виде манифеста.
Java — это не что иное, как набор объ­
чем правилом. Они уместны В манифесте определяется, какой
ектов, которые общаются между собой.
в особых случаях, когда у вас класс в архиве содержит метод
нет нескольких экземпляров/ main(), предназначенный для
объектов. запуска приложения. вы здесь ь 71
Упражнение: поработайте компилятором

П о р а б о т а й т е К ом цш дяйьором

К д ^ ы й , Ja V sL -ф а й л на эпьой, с т р а н и ц е
'Пр^сша^дясть собой, цолНоц,еННЫй,
LbcXo^m iK- ЙР а ш а з а д а ч а — ц р и ,т ь £ о р т ь с .я
К о м и и д я тьо р о м и, оцр^еЛи/И ъЬ, jtee
ли, и,3 HU,X cKoMHU,AU,p/KHtbCjI.
Е сл и , К о м Ш Л Я Н А Я Нс cMo&cfo
црой,ть.ц, у с п е ш н о , к а к
и с п р а в и л и ф а й л ы ? Е сл и , Ж е они,
cK oM U LbA itg/joibcji, КаКой, р е з у л ь т а т * !, н а
э к р а н е £ ы ц о / у ч и л ы ;?

А
class TapeDeck (

boolean canRecord = false; В


class DVDPlayer (
void playTapeO {
System.out.println("пленка проигрывается"); boolean canRecord = false;
}
void recordDVDO {
void recordTapeO { System.out.println("идет запись DVD");
System.out.println("идет запись на пленку"); }
) }
)
class DVDPlayerTestDrive {
class TapeDeckTestDrive { public static void main(String [] args) (
public static void main(String [] args) {
DVDPlayer d = new DVDPlayer();
t.canRecord = true; d.canRecord = true;
t.playTape(); d.playDVD() ;

if (t.canRecord = true) { if (d.canRecord == true) (


t.recordTapeO; d.recordDVDO;

} }
} )
} }

72 глава 2
Упражнение: магнитики с кодом

Магнитики с кедом
Части рабочего Java-приложения
разбросаны по всему холодильни­
ку. Можете ли вы восстановить из
фрагментов кода работоспособную
программу, которая будет выводить
приведенный ниже текст? Некото­
рые фигурные скобки упали на пол.
Они настолько маленькие, что их
нельзя поднять, поэтому разре­
шено добавлять столько скобок,
сколько понадобится.

public static void main(String [] args) {

class DrumKitTestDrive {
— - ■ДМ —

еы зоегь ► 73
Головоломка у бассейна

public class EchoTestDrive {


public static void main(String [] args) {
Echo el = new Echo();

Годо^одомка/ бассейна
in t x = 0;
Ваша задача — взять фрагменты
while ( __________ ) {
кода со дна бассейна и заменить
ими пропущенные участки el.hello();
программы. Вы мажете исполь­
зовать один фрагмент несколько
if ( _________ _ ) {
раз, но не все из них вам приго­
e2.count = e2.count + 1;
дятся. Ваша цель — создать класс,
который скомпилируется, запустится }
и выведет приведенный ниже текст. if ( ___________ ) {
e2.count = e2.count + el.count;
Результат:
}
x = x + 1;
)
System.out.println(e2.count);
}
}

class ___________ {
int ________ = 0;
void __________ {
Призовой вопрос! System.out.println ("привееееет. .. ;
Как бы вы завершили эту голо­ )
воломку, если бы в последней
строке было не 1 0 , а 2 4 ?
Примечание: каждый
фрагмент кода из бас­
сейна можно исполь­
зовать несколько раз!

х <4
х <5 Echo
х >0 Tester
count х> 1 e ch o () e2 = e l;
e l =e1 + 1; co u n t() Echo e2;
e l = count + 1; h e llo () Echo e2 = e l;
e1.count = count + 1; Echo e2 = new Ech o (),
e1 .count = el .count + 1

74 глава 2
Кто я такой?

Команда звезд из мира Java хочет сыграть с вами в игру «Кто я та­
кой?». Они дают вам подсказку, а вы пытаетесь угадать их имена.
Считайте, что они никогда не врут. Если говорят что-нибудь под­
ходящее сразу для нескольких участников, то записывайте всех,
к кому применимо данное утверждение. Заполните пустые строки
именами одного или нескольких участников рядом с утверждени­
ями. Первого мы взяли на себя.
Сегодня участвуют:
Класс М етод О бъект Поле

Я компилируюсь из файла JAVA. Клзсс.

Значения моих переменных


экземпляра могут отличаться
от значений моих полей ввода.

Я выступаю в роли шаблона.

Я люблю что-нибудь делать.

У меня может быть много методов.

Я представляю собой состояние.

Я могу вести себя по-разному.

Я нахожусь в объектах.

Я обитаю в куче.

Меня используют для создания


экземпляров объекта.

Мое состояние может меняться.

Я объявляю методы.

Я могу изменяться во время


выполнения программы.

вы здесь ► 75
Ответы

П о л о м и л и %о
Упражнение class TapeDeck {

boolean canRecord = false;


ОуУфсШ ! void playTape() {

System.out.println("пленка проигрывается");

)
void recordTape() {

System.out.println("идет запись на пленку");

)
}

class TapeDeekTestDrive (
М агнит ики с кодом
public static void main (String [] args) {
class DrumKit {
TapeDeck t =new TapeDeck();
boolean topHafc = true; t.canRecord = true;
boolean snare = true; t.playTape() ;

void playTopHat() { if (t.canRecord = true) (


System.out.printin("дашь дашь ди-дашь"); t. recordTape ();
} )
У нас есть шаблон, теперь мы
void playSnare() { можем создать объект!
System.out.printin(пбах бах ба-бах");
)
>
class DVDPlayer (
boolean canRecord = false;
class DrumKitTestDrive {
void recordDVD() {
public static void main(String [] args) {
System.out.println("идет запись DVD");

}
DrumKit d = new DrumKit();
void ployDVD () {
d.playSnare();
System.out.printinfDVD проигрывается");
d.snare = false;
}
d.playTopHat();
}
if (d.snare = true) {
class DVDPlayerTestDrive f
d.playSnare();
public static void main(String [] args) (
1
DVDPlayer d = new DVDPlayer();

d. canRecord = true;
) В d.playDVDO ;

if (d.canRecord = true) {
I Fite Edit Window Help Dance
d.recordDVD() ;
% java D r u m K i t T e s t D r i v e
)
бах бах ба-бах
) I Строка d.playDVD( ); не будет
динь динь ди-дкнь I | скомпилирована без /метода!

76 глава 2
Ответы

Отк&сукы

Г о л о в о л о м к а ./ б а с с е й н а

public class EchoTestDrive {


К ш о j\ т а к о й ?
public static void main(String [] args) {
Echo el = new Echo();
Я компилируюсь из файла JAVA. Класс.
Echo e2 - new Echo( ); / / правильный ответ
- или - Значения моих переменных
Echo e2 = el; / / бонусный ответ! экземпляра могут отличаться
от значений моих полей ввода. ОЗЪеюлц.
int x = 0;
while ( X < A ) { Я выступаю в роли шаблона. Класс.
el.hello() ;
e l .count = el.count + 1; Я люблю что-нибудь делать. 05ъеюц, Метпод.

if < x == 3 ) { У меня может быть много методов. Класс, оЗЪеюту


e2.count = e2.count +1;
> Я представляю собой состояние. "Переменная экземпляра.
if ( X > О ) {
Я могу вести себя по-разному. ОЗъекч класс.
e2.count = e2.count + el.count;
) Я нахожусь в объектах. Memiog. переменная Экземпляра.
x == x + 1;
Я обитаю в куче. 05ъеюп-
)
System.out.println(e2.count) ;
Меня используют для создания
} экземпляров объекта. Класс.
)
Мое состояние может меняться. ОЗЪеюг), Поле.

Я объявляю методы. Класс.


class Echo {
int court = 0; Я могу изменяться во время
void hello( ) { выполнения программы. 05Ъеют|, поле.
Sys torn.out.println ("п р и в е в а е е т ;
)
}
Примечание: Состояние и поведение свойственны как
классам, так и объектам. Они определяются внутри класса,
но объект ими также обладает. Пока нам все равно, где они на
самом деле обитают.

вы здесь ► 77
3 Примитивы и ссылки

Свои переменные
нужно знать в лицо

Переменные делятся на два вида: примитивы (простые типы) и ссылки.


Пока вы использовали их либо как переменные экземпляра (которые описывают состояние

объекта), либо как локальные переменные (которые объявляются внутри метода). Далее мы

будем применять их в качестве аргументов (значений, передающихся методу из вызываемого

кода) и возвращаемых значений (которые возвращаются методом в вызывающий код). Вы уже

видели переменные, объявленные в качестве простых целочисленных значений (тип i n t ) .

Вы также видели более сложные элементы — строки или массивы. Но в жизни должно быть

что-то помимо чисел, строк и массивов. Как быть с объектом PetOwner с переменной экзем­

пляра типа Dog? Или Cat с переменной экземпляра Engine? В этой главе мы приоткроем завесу

тайны над типами в языке Java и вы узнаете, что именно можно объявлять в качестве перемен­
ных, какие значения присваивать им и как вообще с ними работать.

это новая глаза > 79


Объявление переменной

Объявление переменной
Java заботится о типах. Он не позволит вам сделать
что-либо странное, например засунуть ссылку типа
Giraffe в переменную Rabbit. Java также не разрешит
присвоить число с плавающей точкой целочисленной
переменной, если только вы не скажете компилятору,
что сознательно решили обойтись без точных резуль­
татов (например, убрав дробную часть).
Компилятор может распознать большинство проблем:
R a b b it h o p p e r = new G i r a f f e ( ) ;
Даж е не надейтесь, что это скомпилируется.
Чтобы все эти меры безопасности работали, нужно
указать тип своей переменной. Это целое число? Тип
Dog? Одиночный символ? Как уже говорилось, пе­
ременные делятся на два вида: примитивы (простые
типы) и ссылки. Первые хранят основные значения
(иначе говоря, простые битовые структуры), включая
целые числа, булевы значения и числа с плавающей
точкой. Вторые хранят ссылки на объекты.
Первым делом мы рассмотрим простые типы, а затем
попытаемся разобраться, что на самом деле представ­
ляют собой ссылки на объекты. Но вне зависимости
от типа переменных при их объявлении вы должны
соблюдать два правила.

Переменная долж на иметь тип.


Помимо типа у переменной должно быть имя, чтобы
можно было работать с ней внутри кода.

Переменная долж на иметь имя.

in t co u n t;
К
Имя.

Примечание: когда вы видите выражение -«Объект


типа X», считайте, что тип и класс — синонимы (мы
рассмотрим это в следующих главах).

80 глава 3
Примитивы и ссылки

«Мне, пожалуйста, двойной мокко. Простые типы


Хотя нет, сделайте его цельным» Тип Количество Диапазон
бит значений
Думайте о переменных в Java как о чашках. Кофейных, чайных,
boolean ■ char
больших пивных кружках, стаканах для попкорна, чашечках
с симпатичными изогнутыми ручками, бокалах с металлической boolean (зависит07jvm) true или false
обводкой, которые ни при каких обстоятельствах нельзя ставить char 16 бит от 0 до 65 535
в микроволновую печь. Числовые (все числа со злаком)
Переменная —это просто посуда. Контейнер. Она предназначена Ц е ло ч и с ле н н ы е
для хран ен и я. byte 8 бит о т -128 до 127

У нее есть размер и тип. В этой главе мы сначала рассмотрим пе­ short 16 бит от -32 768 до

ременные (чашки), предназначенные для прост ы х т ипов, а чуть 32 767

позже перейдем к изучению посуды, которая хранит ссыпки на int 32 бит от-2147 483 648
объекты. Будем придерживаться такой аналогии с чашками, что до2 147483647
поможет нам, когда речь пойдет о более сложных вещах. long 64 бит от -9 х 101в
до 9 х 10,в
Примитивы похожи на стаканчики в кофейнях. Если вы бывали
Типы с п л а в а ю щ е й точкой
в Старбаксе, то знаете, о чем идет речь. Стаканчики бывают
float 32 бит о т-3,4 х 1058
разных размеров, и каждый называется по-своему — «ко­
до 3,4 х 10м
роткий», «высокий» и «большое мокко пополам
double 64 бит от ±5,0 х 10 '” 4
с воздушным кремом». до ±1,7 X 10м8
Эти стаканчики выставлены на Объявление переменных
прилавке, так что можно заказать: простых типов и присваивание
Маленьким Низкий Высокий Большой вм значений
int х;
Так и в Java: простые типы имеют разные размеры и на­
х = 234;
звания. Объявляя переменную, вы должны указать
byte b = 89;
для нее конкретный тип. Следующие четы­
boolean isFun = true;
ре контейнера предназначены для
четырех числовых типов Java. double d = 3456.98;
char с = T ;

short int z = x;
boolean isPunkRock;
Каждый контейнер содержит значение, поэтому для простых типов isPunkRock = false;
в Java вместо «Я буду большой кофе по-французски» вы говорите
boolean powerOn;
компилятору: «Мне, пожалуйста, целочисленную переменную с чи­
powerOn = isFun;
слом 90». Но есть одна небольшая особенность. Вы также должны
long big = 3456789;
дать своей чашке им я, поэтому итоговая фраза будет звучать так:
float f = 32.5JQ_
«Мне, пожалуйста, целочисленную переменную со значением 2486
и именем h eig h t». Каждый простой тип имеет фиксированное
количество бит (размер чашки). Далее перечислены размеры шести

e*ec1"e

как £ a*0'*' c_-;4KOa 6 Java


,иаЧ£киЯ c vnoHKou

byte short irrf long floot double


к „ u tv , Jo u b ie .
8 16 32 И 32 64 вы здесь > 81
Присвоение примитивов

Наточите с&ой
"Постарайтесь ничего не рассылать...
' . карандаш—
Проверяйте, помещается ли значение в переменную.
Вы не можете поместить большое
значение в маленькую «чашку». Компилятор не позволит
вам поместить значение
Честно говоря, это можно сделать, но
из большой «чашки»
тогда кое-что потеряется. П роизойдет
в маленькую. Но можно
своего рода переполнение. К ом пиля­ ли перелить содержимое
тор попытается предотвратить такую маленькой чашки в боль­
ситуацию, если увидит, что в вашем шую? Без проблем.
коде какая-то сущность не вмещается
На основании сведений
в контейнер (перем енную /чаш ку), о размере и типе пе­
который вы используете. ременной подумайте,
Н апример, вы не можете «залить» сможете ли вы опреде­
значение типа in t в контейнер размера лить, какое из выражений
допустимо, а какое — нет.
byte, как показано ниже.
Мы пока не рассмотрели
in t х = 24; все правила, поэтому
byte b = х; в некоторых случаях
вам придется угадывать.
//Не сработает! Подсказка: компилятор
всегда заботится
Вы спросите, почему это не работает? Значение х равно 24, значит, оно о безопасности.
полностью совместимо с типом byte. Нам это известно, но компилятора
волнует только тот факт, что вы пытаетесь поместить большую сущность В следующем списке вы­
в маленькую, из-за чего может произойти переполнение. Н е надейтесь, делите допустимые выра­
что ком пилятор будет знать значение переменной х, даж е если вы прямо жения, исходя из того, что
они используются в одном
указали его в своем коде.
и том же методе.
Вы можете присвоить значение переменной несколькими способами:
■ добавить литерал после знака «равно» (х = 12, isGood = tr u e и т. д.);
1. int х = 34.5;
■ присвоить переменной значение, которое принадлеж ит другой пере­ 2. boolean boo = х ;
менной (х = у);
3. int g = 17;
■ использовать выражение, сочетая оба подхода (х = у + 4 3 ). 4. int у = g;
В следующ их примерах значения-литералы выделены полуж ирны м 5- у = у + 10;
шрифтом. 6. short з ;
int size = 32; Объявляем переменную типа int с именем size, 7. s = у;
присваиваем ей значение 32.
8. byte b = 3;
char initial = ’j '; Объявляем переменную типа char с именем initial,
присваиваем ей значение '/'. 9. byte v = b;

double d = 456.709; Объявляем переменную типа double с именем d, 10. short n = 12;
присваиваем ей значение 456.709. 11. v = n ;
boolean isCrazy; Объявляем переменную типа boolean с именем isCrazy 12. byte k = 128;
(ничего ей не присваиваем).
13. int p = 3 * g+y;
isCrazy = true; Присваиваем значение true объявленной ранее
переменной isCrazy.
int у = x + 456; Объявляем переменную типа int с именем у,
присваиваем ей значение, которое является
суммой х(чему бы он ни равнялся) и 456.
82 глава 3
Примитивы и ссылки

Держитесь подальше
о т этого ключевого слова!
nr.pcA^lC° 1
^ **»*«»*.
Вы знаете, что переменны м нужны тип и имя.
Вы уж е изучили простые типы.
VV; '
Но что вы вправе использовать в качестве имен? vjoi^O
М ож но подбирать имена для классов, методов или пе­
ременны х исходя из следую щ их правил (в реальности
все не настолько строго, но их знание убереж ет вас от
.ahпрос
Восемь ПР ГПЫХГПиПОбt: -vntrcng<'oat
,,oat<Jo«We
ош ибок). сиглии-
„ * » * “ » " * * a9„,u.«.»»"“»WU’
■ Имя д о л ж н о начинаться с бук вы , зн ак а п о д ч ер к и ­
вания U или зн ак а д о л л а р а ($). Н ельзя начинать a rrv ^
имя с циф ры . бопыии*
n Careh)UBe3tS v;e доп***
П осле в ерн ого сим вола м ож н о использовать числа o a o P °^ '-WeAB^
б е з ограничений. Главное, не начинать имя с циф ры . спйхсобак.1 ^веннуюФР^'
^ . . вш п р и т т ?с
■ Вы вправе вы брать л ю б о е имя, сл еду я п реды дущ и м
двум правилам, но тол ьк о если он о н е сов п адает с о д ­ D.
ним из зар езер ви р ован н ы х к лю чевы х слов (и др уги х СВ.
названий) в я зы к е Java, к оторы е распознаю тся ком пи­
лятором .
Что бы ты там ни >
Если вы действительно хотите запутать компилятор, попробуйте у к а­ слышал, не давай,
зать в качестве имени зарезервированное слово. цсГ)оу& повторяю, не давай мне
проглотить очередную
p u b lic s t a t ic v o id I большую пушистую
о /1 собаку. /— /
Точно так же зарезервированы названия простых типов: ' им ен.
/
b o o l e a n c h a r b y t e s h o r t i n t l o n g f lo a t d o u b le

К лю чевы х слов гораздо больше, чем перечислено здесь. Д аж е если вам


не нуж но знать, что они означают, вы все равно долж ны понимать, ч ю
их нельзя использовать при именовании переменных. Не пытайтесь
запомнить их сейчас. Чтобы найти в своей пам яти место д л я этого,
вам, вероятно, придется забы ть что-то другое, наприм ер где п рип арко­
ван ваш автомобиль. Н е волнуйтесь — к концу книги вы будете прекра­
сно знать больш инство из этих слов.

Эти слова зарезервированы.


boolean char double float short private

protected abstract final native static strictfp synchronized transient volatile

while switch case default break continue assert

class extends implements import instanceof interface new package super

catch finally throw throws return void const enum

Ключевые слова языка Java и другие зарезервированны е сочетания символов (в случайном порядке). Если вы
укажете их в качестве имен, компилятор очень огорчится.

вы здесь > 83
Ссылки на объекты

Упра&ляем объектом Voa


Вы знаете, как объявить переменную простого типа и присво­
ить ей значение. Н о что делать с непросты ми переменными,
то есть с объектами? Dog d = new Dog();
■ На самом деле не существует такого понятия, как объект­
ная переменная.
d.bark();
■ Есть переменная, ссылающаяся на объект.
■ Переменная, ссылающаяся на объект, хранит биты, кото­ Д у М д С щ е о § Э у \г\ о М.
рые описывают путь для доступа к объекту.
£слт) т п з к ■
■ Она хранит не объект как таковой, а нечто вроде указа­
теля или адреса. Только в Java мы не знаем, что на са­
мом деле находится внутри такой переменной. Но точно
известно, что чем бы она ни была, она всегда представ­
ляет лишь один объект. И JVM умеет использовать ссылку
для его получения.
Н ельзя влож ить объект в переменную. М ы часто думаем об
этом что-то вроде «я передал объект S trin g методу System.
o u t.p rin tln ()» . И ли «метод возвращ ает объект Dog», или
«я поместил новый объект Foo в переменную под названием
m yFoo».
Н а самом деле все не так. Н ет гигантских расш иряемы х
контейнеров, которы е могут подстроиться под размер
любого объекта. О бъект сущ ествует лиш ь в одном
месте — в куче, управляемой сборщ иком мусора
(более подробно читайте об этом далее)!
Х отя переменны е простых типов состоят
из битов и действительно представляю т
свои зн а ч е н и я , ссы лочны е переменные
содерж ат биты, которы е описы ваю т
с п о со б п о л у ч е н и я объект а.
Вы использовали оператор д о ­ о ссЬшоЧкоц
ступа «точка» (.) в сочетании со Переменной т^ипа
ссы лочной переменной, чтобы
Docj как о пчлЬтпс
сказать: «И спользуй элемент .Л.,-
д и стан ц и о н н о го
перед точкой, чтобы дать мне
управления.
элемент, находящ ийся после точ­
ки». Н апример, команда: исполЦзуетпе его, SrnoSbi
ПриксуЬтйатпЬ о5Ъектг\у
m yD og. b a r k ( ) ;
Чупо- тцо с д е л а т ь
означает: «И спользуй объект, на которы й ссы лается перемен (ВЫ^ыВаЯ Метг)о^(л).
ная m yD og, чтобы вы звать метод bark()». Когда вы исполь­
зуете оператор «точка» (.) в соче тании со ссы лкой на объект,
дум айте об этом, как о наж атии кнопок на пульте ди стан ц и ­
онного уп равлени я объектом.
84 глава 3
Примитивы и ссылки

Три шага на пути


к объявлению, созданию
и инициализации объекта.

byte short int long Ссылка


8 16 32 64 (количество битов
'D o g m yD og = n e w D o g ( ) ;
не определено)

Ссылка на объект Всего


Объявляем ссылочную
лишь еше одно значение
переменной.
О переменную.

D o g m yD o g - new D og<) ;
Нечто такое, что хранится внутри «чашки».
Это говорит JVM, что она должна вы­
Только в данном случае значение — это делить место в памяти для ссылочной
пульт дистанционного управления. переменной и назвать ее myDog. Ссы­
лочная переменная навсегда получает
Переменная п р о сто го ти п а тип Dog. Иными словами, это пульт
управления, у которого есть кнопки
b y te х = 7,-
для работы именно с объектом Dog,
Биты, представляющие число 7, П ростого а не Cat, Button или Socket.
хранятся в переменной. тг|иП4.
byte
Создаем объект.
D og myDog ** n e w D o g ( )
D o g m yD o g = n e w D o g ( ) ; Здесь JVM получает приказ выде­
лить память в куче для объекта
Биты, описывающие способ получить
Dog (позже вы значительно больше
объект Dog, хранятся в переменной.
СсЬилоЧкое узнаете об этом процессе, особенно
НосампосебеобъектDogневпе­ Значение. в главе 9). Объект Dog
ременной!

Значение переменной простого типа представляет


Связываем объект
собой значение (5, - 2 5 , 7 о1}. , и ссылку.
Значение ссылочной переменной —• это биты, опи­ D og rayDog = new D og () ;
сывающие способ получения конкретного объекта. Присваиваем ссылочной
переменной myDog новый
Вы ке знаете (и вам должно быть все равна), как объект типа Dog. Другими
конкретная версия JVM реализуем ссылки на объек­ словами, программируем пульт
ты. Конечно, это могут быть указатели цр указате­ управления.
ли на... Но даже если вы знаете, то все равно не Объект Dog
можете использовать эти б>ты ни для чего другого,
хроме доступа к объекту.

Нам не важно, сколько нулей и единиц хранится в ссылочной переменной. Это


может зависеть от конкретной JVM ияи от фазы Луны.
Dog
вы здесь ► 85
Ссылки на объекты
Р А Э О ЕЛА Ч Ш ЗИ Е
Э то не _ Я З Ы К А tfA V A
глупы е Вопросы Интервью этой недели:
Объектная ссылка
f Насколько велика
ссылочная переменная?
Headfirst: Итак, расскажите нам, как поживает о6л>ектная ссылка.
Ссылка: У меня довольно простая жизнь. Я — дистанционный пульт управления,
Uт Это неизвестно. Где-то и меня могут запрограммировать для манипуляции разными объектами.
внутри нее есть указатели,
но к ним нельзя получить Headfirst: Вы имеете в виду разные объекты на протяжении одной сессии? Напри­
доступ. Вам это просто мер, можете ли вы ссылаться на объект Dog, а через пять минут на объект Саг?
не нужно. Но если вы очень Ссылка: Конечно, нет. Меня объявляют лишь для одного объекта. Если я управляю
хотите понять, как выглядит объектом Dog, я уже никогда не смогу указывать (ой, мы ведь не должны говорить
ссылка, можете предста­
«указывать»!), то есть ссылаться пи на что другое, кроме объектов типа Dog.
вить ее в виде 64-6итного
значения. Однако, рассуж­ Headfirst: Значит ли это, что вы можете ссылаться только на один объект Dog?
дая о вопросах выделения Ссылка: Нет. Я могу ссылаться на один объект Dog, а через пять минут —уже на дру­
памяти, вы должны бес­ гой. Если объект имеет тип Dog, я могу быть перенаправлена (как пульт управления
покоиться о том, сколько
перепрограммируется для другого телевизора) на немо. Кроме случаев... Хотя нет, не
объектов (а не ссылок на
обращайте внимания.
объекты) создаете и на­
сколько они большие. Headfirst: Нет уж, не останавливайтесь. Что вы собирались сказать?
Ссылка: Вам вряд ли захочется обсуждать это сейчас, но я попробую рассказать
в двух словах. Если я помечена как final и мне присвоили объект Dog, то я уже ае
Ф: Означает ли это, что
смогу ни с чем работать, кроме этого объекта Dog. Иначе говоря, мне нельзя будет
все ссылки имеют одина­
ковый размер независимо присвоить никакой другой объект.
от величины объектов, на Headfirst: Вы правы, не будем говорить об этом сейчас. Значит, кроме тех случаев,
которые они ссылаются? когда вы помечены как final, вы можете ссылаться сначала на один объект типа Dog,
а позже на другой. А можете ли вы не ссылаться вообще, ни п а ч т о ? Можете ли не

О; Да. Все ссылки


быть ira для чего запрограммированной?
одной версии JVM будут Ссылка: Да, но мне неприятно об этом говорить.
иметь одинаковый размер Headfirst: Почему?
независимо от объектов,
на которые они указыва­ Ссылка: Потому что в таких случаях я полный ноль (пи 11), и это меня расстраивает.
ют. Но каждая JVM может Headfirst: По той причине, что у вас нет значения?
использовать собственный
Ссылка: Ox, n u l l — это и есть значение. Я остаюсь пультом управления, но это
способ представления
то же самое, что купить меля и принести в дом, где пет ни одною телевизора. Я не
ссылок, поэтому от версии
запрограммирована и не могу ничем управлять. Пользователи сутками напролет
к версии размеры ссылки
могут изменяться. будут нажимать мои кнопки, но ничего хорошего из этого нс выйдет. Я чувствую
себя такой бесполезной и зря трачу свои биты. К счастью, их не так много, но псе же.
Меня устанавливают в n u l l (распрограммируют), и значит, н икт о не может полу­
• Можно ли выпол­ чить тот объект, на который я ссылалась раньше.
нять арифметические
операции со ссылочными Headfirst: И это плохо, потому что...
переменными, инкремен­ Ссылка: Вы еще спраш ивает е? Сначала я выстраиваю отношения с объектом, нала­
тировать их, как в языке С? живаю связь, а затем нас внезапно безжалостно разлучают. И я никогда больше не
увижу его, потому что теперь он первый кандидат [ режиссер, включите трагическую
музыку] на свидание со сборщ иком м усо р а. (Всхлип.) Думаете, программист хотя бы
0: Нет. Java — это не С.
осознает, чт о натворил? (Всхлип.) П о ч ем у я не могу быть примитивом? Я н е н а в и ж у
бы т ь ссы лкой . Ответственность, все эти разорванные связи...
86 глава 3
Примитивы и ссылки

Ь куче пос) управлением


с/орш икз мусора
Book Ь = new B o o k ( ) ;

Book с = new B o o k ( ) ;
Объявляем две ссылки типа Book.

edcp,.
Создаем два новых объекта Book.
Присваиваем ссылочным перемен­
ным объекты типа Book.
Book
Два объекта Book теперь находят­
ся в куче.
Ссылок: 2.
Объектов: 2. Book

Book d = с ;
Объявляем новую ссылку типа Book.
Вместо того чтобы создавать новый,
третий по счету, объект Book, при­
сваиваем ссылке значение перемен­
ной с. Мы как бы говорим: «Возьми
биты из с, скопируй их и помести эту
копию в d».
П ер ем ен н ы е с и d ссы лаю тся на
оди н и тот ж е о б ъ е к т .
Book
Ссылки с и d хр ан я т д в е р а зн ы е
копии о д н о г о и того ж е зн а ч е­
ния. Д в а пульта упр авл ен и я д л я
о д н о г о т е л ев и зо р а . подупр*
Ссылок: 3. Book
Объектов: 2. Book

с = b ;
Берем значение переменной
Ь и присваиваем его переменной
с. Сейчас вам уже известно, что
это означает. Биты внутри пере­ О бъе^
менной Ь копируются, и новая ко­
пия помещается в переменную с.
И Ь, и с ссы л аю тся на оди н
ь
и тот ж е о б ъ е к т .
Ссылок: 3. Book
Объектов: 2.

вы здесь ► 87
Объекты в куче

Ж изнь и см ер ть & куче

Book b = new B o o k ( ) ;

Book с = new B o o k ( ) ;
Объявляем две ссылки типа Book.
Создаем два новых объекта Book.
Присваиваем эти объекты ссылоч­
ным переменным.
Два объекта Book теперь находятся Book
в куче.
Активных ссылок: 2.
Куча под упо*
Активных объектов: 2.

Ь = с;
Берем значение переменной с и присва­
иваем его переменной Ь. Биты внутри nDVJLMdHKOU
переменной с копируются, и новая копия
помещается в переменную Ь. Обе пере­
менные хранят одинаковые значения.
И Ь , и с ссы л аю тся на оди н и тот
ж е о б ъ е к т . О бъ ек т Л становится
н едоступ н ы м и п р и го ден дл я о б ­
р а б о тк и сбор щ и к ом м усор а (СМ). 'dm
Активных ссылок: 2.
Book
Доступных объектов: 1.
Недоступных объектов: 1.
Первый объект, на который ссылалась Кучапод
переменная Ь, больше не имеет ссылок.
Он недоступен. Book

с = n u ll;
Присваиваем переменной с значение ftuMez-o н е
n u l l . Это превращает ее в нулевую ссылку,
•ц е н и л о с ь . ^ ч е г о не
то есть она больше ни на что не ссылается.
Но это по-прежнему ссылочная перемен­ ЭООЛЦ-'Я''' r\oKd
ная, и ей все еще можно присво­ о* 2 \ c c b D r t e ^ 9- н й
ить другой объект типа Book.
О бъ ект 2 ещ е и м еет ак ти в­
ную ссы л к у (Ь), значит, он
н е м о ж е т бы ть отд а н на
°С ъ е ^ °
о б р а б о т к у СМ.
Активных ссылок: 1. Book
Нулевых ссылок: 1.
Доступных объектов: 1. ^ Ч е го Куча под упр®5
(н и з ^ я ,нд)-
Недоступных объектов: 1. не^<
88 гла ва 3 Book
Примитивы и ссылки

Массив как подставка для стаканов


Объявляем переменную целочисленного массива. Переменная
О массива — это пульт управления объектом A rray.
i n t [ ] nouns ;
Создаем новый целочисленный массив
с семью элементами и присваиваем его ранее
объявленной переменной nums с типом i n t [ ] .
moms = new i n t [ 7 ] ;
Присваиваем каждому элементу
массива целочисленное
значение.
Помните, что элементы Се/Ab переменных щх\уе\ ttyt
целочисленного массива —
это всего лишь переменные
типа int.
nums [0 ] 6;
nums [1 ] 19;
nums [2 ] 44;
norms [ 3 ] 42;
norms [4 ] 10;
■s. v/;l 1"
nums [5 ] 20; 'nums
norms [ 6 ] l;

in t[]
Пре^стг\^-ПЯетг\ со5ой о^Ъектп, хотпЯ #се его
Массивы —' тож е объекты семЬ Э лем ентно# имеуотн прострой ттпиг)-
Стандартная библиотека в Java переменная. Все, что вы можете ющей странице вы увидите, как
содержит множество сложных поместить в переменную, может это делается.
структур данных, включая ас­ быть присвоено элемент у м а с­ Рассматривая рисунок, приве­
социативные массивы, деревья сива того же типа. В массиве денный выше, не упустите один
и множества (см. Приложе­ типа int (int[ ]) каждый элемент ключевой момент: массив — это
ние Б). Массивы лучше всего имеет тип int. В массиве типа всегда объект, даже если он х р а ­
подходят для создания упоря­ Dog (D o g []) каждый элемент нит элементы простых типов.
доченного, эффективного спи­ может хранить... объект Dog? У вас может быть массив,
ска элементов. Они предостав­ Нет, вспомните, что ссылочные который объявлен для хране­
ляют быстрый произвольный переменные хранят всего лишь ния простых значений. Иными
доступ, позволяя использовать ссылки (пульты управления), словами, объект массива может
индекс (позицию ) для получе­ а не сами объекты. Поэтому содержать элементы, которые
ния элемента списка. в массиве типа D og каждый имеют простой тип, но сам
Каждый элемент в массиве — элемент может хранить пульт не может быть примитивом.
всего лишь переменная. Иначе для управления объектом Dog. Вне зависимости от содержи­
говоря, это один из восьми Конечно, нам все еще нужно мого массив всегда остается
простых типов, или ссылочная создать этот объект, и на следу­ объектом!
ew здесь ► 89
Массив элементов Object С

Создадим массив объектов Voa

Объявляем переменную-массив Dog


D o g [] p e ts;

Создаем новый массив типа "Род


длиной 7 и присваиваем его -

ранее объявленной переменной


pets С ТИПОМ Dog [j.

p e ts = new D o g [ 7 ] ;

Ч т о мы упустили ^
Объекты Dog! Мы име­
ем массив ссылоктипа
Dog, а не самих объек­ О бъект м ассива ти п а Dog (D og[])
тов'. Dog[]

Создаем новые объекты


Dog и присваиваем их
элементам массива. ,0 bJe,
Помните, элементы
в массиве — это всего лишь
ссылки типа Dog. Нам все
еще нужны сами объекты!

p e ts[0 ] = new D o g ( ) ;
p e ts [l] = new D o g ( ) ;

Наточите cE>ou
карандаш"

Какое значение имеет элемент


pets[2]?________________________
С помощью каких команд мож­
но заставить элемент pets[3]
pets
ссылаться на один из двух
О бъект м ассива ти п а Dog (Dog[])
существующих объектов Dog?
Dog[]

90 глава 3
Примитивы и ссылки

Управляем объектом 1?од


с помощью ссылки
D og fid o = new D o g () ;

f f id o . name = "Ф идо";


пате
М ы создали объект D og и ис­
bark() пользовали оператор доступа
eat() в сочетании со ссы лочной пе­
chaseCatl) ременной f i d o для получения
доступа к переменной паше.* О б ъ еХ $

М ож но задействовать ссы лку


fid o д л я доступа к методам
b a rk (), e a t() или chaseC ateQ .
f id o .b a r k () ; D og
f id o . c h a s e C a t () ;
Ж
lava заботится о типах Ч т о происходит, если ссылка
О бъявив м ассив, вы м ож ете Разм ®'^ из9ос| н аходи тся Ь массиве
слать в нем элем енты то лько та к о го
ж е ти п а, что и у сам ого м ассива. М ы знаем, что можем получить доступ
к переменны м экзем пляра и методам
К примеру, вы не вправе поместить
объекта D og с помощью оператора
ссы лку на объект C at в массив ти п а D 9
(пользователь решит, что в массиве м огут доступа, но как?
находиться только ссы лки ти п а иод, Если Dog находится в массиве,
попытается вызвать у у нас нет имени переменной (вроде
метод bark и очень удивится, обнаружив
fid o ) . Вместо этого мы используем
С таивш ийся объект Cat). Нельзя т ^ ж е
поместить переменную double в массив обозначение массива и наж имаем
типа int (это переполнение, п о м н и теД кнопку на пульте (оператор «точка»),
Однако можно поместить в такой массив получая доступ к объекту по
переменную типа byte, так как этот ти указанном у индексу (п ози ц и и ):
всегда помещается в контейнере размера
D o g [] m yDogs = new D o g [ 3 ] ;
int Это неявное приведение типов,
робности м ы рассмотрим позже, а пока m y D o g s[0 ] = new D o g ( ) ;
запомните, что компилятор не позволит
вам поместить неподходящий элем ент m y D o g s[ 0 ] .nam e = "Фидо";
в массив исходя из объявленного типа. m yDogs [0 ] .b a r k ( ) ;

"Да, мы знаем, что здесь не демонстрируются возможности


инкапсуляции, но пытаемся рассказать все максимально просто.
А инкапсуляцией мы займемся в главе 4.

вы здесь > 91
Использование ссы лок

class Dog {
String name;
Приме» класса 'Род
public static void main (String!] args) { Dog
1
if Создаем объект Dog и подучаем к нему '•>л
Dog dogl = new Dog();
name
dogl.bark(); bark()
dogl.name = "Барт"; eat{)

// Теперь создадим массив типа Dog


Результат:
chaseCatd
|
Dog[] myDogs = new Dog[3];
// и поместим в него несколько элементов
| File Edit Window Неф Howl 1
myDogs[0] = new Dog();
% ja v a Dog
myDogs[1] = new Dog();
n u l l с к а з а л Гав!
myDogs[2] = dogl; Имя п о с л е д н е й с о б а к и — Б а р т
Фред с к а з а л Г а в !
// Теперь получаем доступ я объектам Е
Джордж с к а з а л Г а в !
!i с помощью ссылок из массива
Б арт с к а з а л Гав!
myDogs[0].name = "Фред";
myDogs[1].name = "Джордж";

if Хмммм... какое имя у myDogsf2]? --------КЛЮЧЕВЫЕ МОМЕНТЫ ---------


System.out.print("Имя последней собаки - ");
■ Переменные разделяются на два вида:
System.out.printIn(myDogs[2].name); примитивы (простые типы) и ссылки.
■ При объявлении переменных всегда нужно
if Теперь переберем все элементы массива
указывать имя и тип.
•'/ и вызовем для каждого метод bsrk(3 ■ Переменные простого типа содержат биты,
int х = 0; представляющие значение (5, 'a', true,
while(х < myDogs.le 3.1416 и т. д.).
■ Ссылки включают биты, описывающие спо­
myDogs [х] .barkd ;
соб получить объект в куче.
x = x + 1; ■ Ссылочная переменная похожа на дистан­
} ционный пульт управления. Используя
оператор «точка» (.) в сочетании со ссы ­
}
лочной переменной, вы как бы нажимаете
кнопки на пульте для получения доступа
public void bark() (
к методам или переменным экземпляра.
System.out.printIn(name + "сказал Гав!"); ■ Ссылочная переменная имеет значение
} n u l l , если не ссылается ни на какой объект.
■ Массив — это всегда объект, даже если он
public void eat() ] )
объявлен для хранения простых значений.
public void chaseCat() { i Не бывает массивов простого типа, есть
} массивы, которые хранят примитивы.

92 глава 3
Упражнение: поработайте компилятором

Упражнение П о р а б о т а й т е К о м п и л ято р о м

К ^ 5 Ы й , ц,з c Ja V a -^ a iiA o g н а этк.оц,


стьрани,и,е — цолноц.енныц, ц с / о ^ н а К .
1?aiua за д а ч а — и р и т ь ^ о р т ь с ^
К оМ Ц И Д Я ^0? ^ U. 0tipc.5cAU.Tbb, &сс ли,
ф а й л ы сК ом ци>ли.р/ю тьс.я. Бели.
К о м ш А я и А Я не смоскеть
tip o iltb a / c tic iu H o , К аК §ы ц,;с
асц раМ тье?

А В
c l a s s Books { c l a s s Hobbits {
String title;
String author; S t r i n g name;

)
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [] args) (
c l a s s B o o k sT estD riv e {
p u b lic s t a t i c v o id m a in ( S t r in g [] a r g s ) { Hobbits [] h = new H o b b i t s [3 ];
i n t z = 0;
Books [] myBooks = new B o o k s (3 ];
i n t x = 0; while (z < 4) {
myBooks[0J. t i t l e = "Плоды Java"; z = z + 1;
myBooks[ 1 ] . t i t l e = "Java Г этсби"; h [ z ] = new H o b b i t s ( );
myBooks[ 2 ] . t i t l e = "Сборник рецептов h [ z ]. n a m e = "Бильбо";
no Java"; if (z == 1) {
myBooks[ 0 ] .a ut ho r = "Боб"; h [ z ]. n a m e = "Фродо";
m yBooks [ 1 ] .a ut ho r = "Сью "; }
myBooks[ 2 ] .a ut ho r = "Ян"; if (z == 2) {
h [ z ] . n a m e = "Сэм” ;
while (x < 3) { }
System .out.print(m yB ooks[x].title); S y s t e m . o u t . p r i n t ( h [ z ] . n a m e + " - ");
S y s t e m . o u t . p r i n t (", автор"); S y s t e m . o u t . p r i n t l n ("имя хорошего
System.out.println(myBooks[x].author); хоббита");
x = x + 1; }
} }
} I
}
вы здесь ► 93
Упражнение: магнитики с кодом

Магнитики с
Части рабочего Java-приложения разбро­
саны по всему холодильнику. Можете ли
вы восстановить из фрагментов работо­ = index[у];
способную программу, которая выведет
на экран текст, приведенный ниже? Не­
которые фигурные скобки упали на пол;
они настолько маленькие, что их нельзя
поднять. Можете добавлять столько ско­
бок, сколько понадобится.

int ref;

while (у < 4) {

index[0]

i n d e x [1]
index[2]

index[3]

String [] islands = new String[4];


т т г '------ Гцгеяв то-CTJ

94 глава 3
Головоломка у бассейна

class Triangle { Иногда Ml* пренебрегаем


double area; отпяельишл K/WCCOMд л я
int height; -тедаро&лниЯ. ^ о Ь Ы
Г о д о $ о д о м К а у б а ссе й н а cox^ hW месило на с п ^ М й * -
int length;
Ваша задача — взять фраг­
менты кода со дна бассейна
public static void main(String [] args) {
и заменить ими пропущен­
ные участки программы.
Можно использовать один
while ( __________ ) {
фрагмент несколько раз,
но не все из них вам пригодят­
ся. Ваша цель — создать класс, .height = (x + 1) * 2;
который скомпилируется, запу­ ■length = x + 4;
стится и выведет приведенный
ниже текст.
Результат: System.out.print("треугольник "+x+", зона");
File Edit Window Help Bermuda System.out.println(" = " + ______ .area);

x = 21;
Triangle t5 = ta[2];
ta[2].area = 343;
System.out.print("y = " + y);
System.out.println(", зона t5 = "+ t5.area);
Призовой вопрос!
}
Если хотите получить призовые
баллы, используйте фрагменты из void setAreaO {
бассейна, чтобы заполнить пропуски ____________ = (height * length) / 2;
в показанном выше результате рабо­
ты программы.
Примечание: каждый
фрагмент кода из бас­
сейна можно исполь­
зовать несколько раз!
4, t5 зона = 18.0
J f / area 4, t5 зона = 343.0
ta.area 27, t5 зона = 18.0 int х;
Jjfzp r x ta.x.area 27, t5 зона = 343.0 int у; х = х + 1; ta.x
v ta[x].area int х = 0; х = х + 2; ta(x)
y ta[x] = setAreaO; х = х -1 ;
int х = 1; ta[x]
Triangle [ ] ta = new Triangle(4); ta.x = setAreaO;
int у = х;
Triangle ta = new l ] Triangle[4]; ta[x].setArea(); 28 П ta = newTriangleO;
Triangle [] ta = newTriangle[4]; .... ta[x] = newTriangleO;
— ______ *****/0в0*уР' ta.x = newTriangleO;

вы здесь » 95
Куча проблем

c l a s s H e a p Q u iz {
иробиеил in t id = 0;
p u b lic s t a t i c v o i d m a i n ( S t r i n g [] a r g s )
Справа представлена небольшая in t x = 0;
Java-программа. В коде до строки H e a p Q u iz [ ] h q = n e w H e a p Q u i z [ 5 ] ;
с комментарием создаются объекты w h ile ( x < 3 ) {
и ссылочные переменные. Ваша зада­ h q [ x ] = new H e a p Q u iz ( ) ;
ча — определить, какая переменная h q [x ]. id = x;
ссылается на какой объект. Не все
X = X + 1 ;
ссылки будут использованы, а на j
некоторые объекты нужно ссылать­
ся несколько раз. Нарисуйте линии, hq [ 3 ] - h q(1];
соединяющие ссылки с соответству­ h q [4 ] — h q[1];
ющими объектами. hq [3 ] = n u ll;
Подсказка: вероятно, вам придет­ hq [ 4 ] - h q[0];
ся рисовать, как на с. 87 и 88 (хотя, h q [0 ] = h q [3);
может, вам это не нужно). Вы можете hq [ 3 ] = h q[2];
рисовать карандашом и затем стирать hq [ 2 ] = h q [0];
ластиком линии, соединяющие ссылку / / Делаем что-то
(пульт управления) с объектом. }
}

Ссылочные переменные: Объекты HeapQuiz:

CoeQ uH im e

hq[4]
96 глава 3
Дело о похищении ссылок
Дело о похищении ссылок
Темная ночь. Шторм. Тавни расхаживала но офису, в котором работали программи­
сты. О на знала, что все разработчики очень заняты, и ей хотелось им помочь. Нужно
было добавить новый метод в главный класс, который необходимо загрузить на новый
совершенно секретный мобильный телефон с поддержкой Java, разрабатываемый для
клиента. Динамической памяти (кучи) в телефоне чрезвычайно мало — об этом зна­
ли все. Привычный офисный гул быстро стих, как только Тавни подошла к доске для
рисования схем. О на кратко описала возможности метода и обвела взглядом всех своих
подчиненных. «Ну что ж, парни, пришло время истины, — промурлыкала она себе под
нос. — Кто сможет придумать наименее требовательный к памяти вариант этого метода,
того я возьму с собой на вечернику в Майами, которую наш клиент устраивает завтра.
Придется помочь мне установить новое программное обеспечение».
На следующее утро Тавни приш ла в офис в своем коротком гавайском платье.
«Господа, — улыбнулась она, — самолет вылетает через несколько часов, покажите
же мне результаты ваших стараний!» Первым вышел Боб. Как только он начал
изображать свои идеи на доске, Тавни сказала: «Ближе к делу, Боб, покажи
П ^ ш а м ц > н /? ь н ы & мне, как ты управляеш ь обновлением списка объектов с контактами». Боб
быстро набросал фрагмент кода на доске:
Contact [] са = new Contact[10];
while ( у. < 10 ) { // Создаем 10 объектов Contact
са[х] = new Contact();
х = х + 1;
}
// Делаем сложное обновление списка
// с объектами Contact с помощью массива са
«Тавни, я понимаю, что у пас ограниченный размер памяти, но в твоем задании гово­
рится, что мы должны иметь возможность работать с информацией каждого из десяти
допустимых контактов. Это лучшее, что я смог придумать», — сказал Боб. Кент, вышед­
ший следующим, уже представлял, как будет пить кокосовые коктейли вместе с Тавни.
«Боб, — сказал он, — твое решение слегка нелепое, не находишь?» И с ехидной улыбкой
добавил: «Взгляни на это, крошка».
Contact refc;
while ( х < 10 ) { // Создаем десять объектов Contact
refc = new Contact();
x = x + 1;
>
// Делаем сложное обновление списка
// с объектами Contact с помощью переменной refc

«Я сохранил ценную память, сэкономив на ссылочных переменных, Боб, так что мо­
жешь спрятать свои солнцезащ итные очки», — насмешливо сказал Кент. «Попридержи
лошадей, Кент! — отвесила Тавни. — Ты сохранил немного памяти, это правда. Н о со
мной едет Боб».

П очем у Тавни предпочла м ет од Б оба, хот я Кент использовал меньш е памят и ?

вы здесь > 97
Ответы П о р а б о м и л и К ом пилятором

От^е-ПьЫ class Books {


String title;
String author;
}
class BooksTestDrive {
public static void main(String [] args) (
Books [] myBooks = new Books[3];
int x = 0;
A myBooks[0] = new BooksO; Помните: но сомом
myBooks[l] = new BooksO; деле мы должны
М агнитики с кедом создать объекты
myBooks[2] = new BooksO: Book!
class TestArrays { myBooks[0].title = "Плоды Java";
myBooks[1].title = "Java Гэтсби";
public static void main(String (] args)
myBooks[2].title = "Сборник рецептов no Java";
int (] index = new int[4];
myBooks[0].author = "Боб";
index[0] = 1; myBooks[1].author = "Сью";
index[1] = 3; myBooks[2].author = "Ян";
index[2] = 0; while (x < 3) (
index[3] = 2; System.out.print(myBooks[x].title);
System.out.print(" by ");
String [] islands = new String[4];
System.out.println(myBooks[x].author);
islands[0] = "Бермуды";
x = x + 1;
islands[1] = "Фиджи";
1
islands[2] = "Азорские острова"; }
islands[3] = "Косумель";
int у = 0;
class Hobbits {
int ref;
String name;
while (y < 4) (
public static void main(String [] args) {
ref = index[y]; Hobbits [] h = new Hobbits[3];
System.o u t . print ("острова = "); int z = - 1: Помните: массив
System.o u t . println(islands[ref]); while (z * 2) { начинается с нулевого
элемента!
у = у + 1; z = z + 1;
h[z] = new Hobbits();
)
j h[z].name = "Бильбо";
)
* if (z == 1) <
) h[z].name = "Фродо";
}
I File Edit Window Help Bikini
if (z = 2) [
h[z].name = "Сэм";
;% java T e s t A r r a y s }
остсоза = Фкд«к System.out.print(h[z].name + " - ");
острсза = Косумель System.out.println("HMS хорошего хоббита");
острова = Бермуды
лULxpyiJa Sb'AYvAviffi лл>яллиa
г гг лтаа —~ лЗурСлИс }
)
\

98 глава 3
Ответы

Разгадка дела о похищении ссылок

Т авии смогла увидеть в методе Кента серьез­


ны й недостаток. О н на самом деле исполь­
зовал меньш е ссы лочны х переменных, чем
Боб, но у него не было возмож ности полу­
Г о л о в о л о м к у бассейна чить доступ ни к одному объекту контактов,
кроме последнего созданного. П ри каж дой
class Triangle ( итерации ц икла он присваивал новый объект
double area; одной и той ж е переменной, а объект, на
int height; которы й эта переменная ссы лалась ранее,
int length; становился недост упен. Н е имея шансов по­
public static void main(String [] args) { лучить доступ к девяти из десяти созданных
int x = 0; объектов, метод К ента оказался бесполезным.
Triangle [ ] ta = new Triangle[4];
(Разработанную программу ждал большой успех, а клиент выдал
while ( x * 4 ) | Тавни и Бобу дополнительную неделю отпуска на Гавайях. И мы
ta[x] = new TriangleO: рады сообщить, что вы получите нечто похожее, прочитав эту
to[x] .height = (x + 1) * 2; книгу.)

ta[x] .length = x + 4;
ta[x].set4rea0;
System, out. print ('‘треугольник "+x+", зона");
System.out.println(" = " + ta[x].area);
иробдеал
x = x ♦ 1;
) Ссылочные переменные: Объекты HeapQuiz:
int у = x;
x = 27;
Triangle t5 - ta[2);
ta[2 ].area = 343;
System.out.print(" у = " + у) ;
System.out.println(", зона t5 = " + t5 .area);
)
void setArea() {
a re a — (height * length) / 2;
}
}
[Pile Edii Window Help Be/muda
fcjava T r i a n g l e
треугольник 0, зо ва = 4 . 0
т р е у г о л ь н и к .1 . зона = 1 0 .0
треугольник 2, зона = 18 .0
треугольник 3 ,.з о н а = 2 8 ,0
у - 4, t5 зона - 343

вызоесь > 99
4 Методы содержат переменны е экземпляра

Пак себя ведут объекты


Я просто
обязан изменить
ее положение!

Состояние влияет на поведение, а поведение — на состояние.


Вы знаете, что объекты характеризуются состоянием и поведением, которые представ­
лены переменными экземпляра и методами. До этого момента вопрос о связи между
состоянием и поведением не поднимался. Вам уже известно, что каждый экземпляр класса
(каждый объект определенного типа) может иметь уникальные значения для своих пере­
менных экземпляра. У первого объекта типа Dog есть имя (переменная пате) Фидо и вес
(переменная weight) 30 килограммов. Второй объект этого типа носит имя Киллер и весит
4 килограмма. И если класс Dog содержит метод makeNoiseO, будет ли 4-килограммовая
собака лаять более убедительно, чем 30-килограммовая (при условии, что это тявканье
можно назвать лаем)? К счастью, в этом и состоит суть объектов — их поведение зависит
от состояния. Иными словами, м е т о д ы и с п о л ь зу ю т зн а ч е н и я п е р е м е н н ы х э к з е м п л я р а .
Можно сказать что-то вроде «если собака весит меньше 6 килограммов, издаем тявканье,
иначе...» или «увеличиваем вес на 2». В э т о й г л а в е в ы у з н а е т е , к а к и зм е н и т ь со с т о я ­
ние объект а.

это новая глава > 101


Объекты характеризуются состоянием и поведением

Помните: класс описывает,


что объект зн ает и Желает
Класс — это шаблон для объекта. Разраба- ^
ты вая класс, вы описываете, как JV M долж - • »£рвМ €ИИЫ б
на создать объект указанного типа. Вам уже экзем п ляра
известно, что каж ды й объект определенного (состояние)
типа мож ет иметь разны е значения переменны х
экземпляра. Но как насчет методов? Методы
(поведение)
М о ж е т ли м етод каждого из объектов
определенного ти п а иметь собственное
4 \5 № b „аров
поведение?
Ну... что-то вроде того.*
Все экзем пляры конкретного класса имеют
одни и те ж е методы, которые могут вести
себя по-разному, в зависимости от значений
переменны х экзем пляра.
К ласс Song содерж ит два поля — title и artist.
М етод р1ау() проигры вает композицию,
выбор которой будет зависеть от поля title для
конкретного экзем пляра. В ы зы вая метод р1ау()
из разны х экзем пляров, вы можете услы ш ать
различны е композиции — «Politik», «D arkstar»
или другую. О днако код метода остается
прежним.
v o i d p l a y () {
s o u n d P la y e r .p l a y S o u n d ( t i t l e ) ;
>
Song t2 = n e w S o n g ();

t2.setArtist("Travis");
о At Song
Song
s3 .p la y ();
t2 .p la y () ;

/
t 2 .s e t T i t l e ( " S i n g " ) ;

Song s3 = n e w S o n g Q ;
* * З Ц з ° ^ Метпо^с!
s 3 .s e t A r t i s t ("Sex Pistols")
Р ^ О и з Э щ ого
s3. setT i t l e ("My Way");
Э кзем пляра п р и Ц и тп
К ^оспроиз^е^екик? песни
(но не тпои,
Каупор^ук) поетп CuHdTnpd).
*Еще один поразительно четкий ответ!

102 глава 4
Методы содержат переменные экземпляра

Размер влияет
на громкость лая
М аленькие собаки лаю т не так, как большие. Класс
D og содерж ит переменную экзем пляра size, которая
используется методом bark() дл я определения вида

class Dog {
int size;
String name;

void bark() (
if (size > 60) (
System.out.println("Гав Гав!");
} else if (size > 14) {
System.out.println("Вуф Вуф!”);
} else {
System.out.println Г'Тяф Тяф!”) ;
}
}

“.«W4
\

class DogTestDrive (

public static void main (String[] args) {


Dog one = new Dog() ;
one.size = 70;
Dog two = new Dog();
two.size = 8;
Dog three = new Dog();
three.size - 35;

one-bark();
two.bark();
three.bark();
}
}

вы здесь > 103


Объекты характеризуются состоянием и поведением

можете передавать методу разные значения


К ак и в любом другом язы ке программирования, в Jav a вы можете передавать
значения своим методам. К примеру, укажите объекту Dog, сколько именно раз
нуж но пролаять:
d .b a rk (3);
В зависимости от опы та и личных предпочтений для обозначения передаваемых
в метод значений вы можете использовать два термина — аргументы или параме­
тры. Хотя с точки зрения компьютерных наук эти понятия не тождественны, мы
не будем отвлекаться на такие мелочи. М ожете называть их, как вам вздумается
(аргументами, пончиками, комками шерсти и т. д.), но мы будем придерж иваться
следующ их правил.

Метод использует параметры. Вызывающий код передает аргументы.


Аргументы — это значения, которые вы передаете методам. А ргум ент (значение
наподобие 2, "Foo" или ссылки на объект Dog) превращ ается в парамет р. В свою
очередь, это не что иное, как локальная переменная, то есть переменная с именем
и типом, которая может быть использована внутри метода.
Н о есть один важный момент: если метод принимает параметр, вы обязаны ему
что-нибудь передать. П ри этом передаваемое значение долж но бы ть соответству­
ющего типа.
Dog d = new Dog() ;
Вызываем метод bark из ссылки на
О объект Dog и передаем ему значение 3
(в качестве аргумента для метода).
d.bark(3);
V ,
Биты, представляющие
целочисленное значение 3,
передаются в метод bark.

О Биты размещаются в параметре


numOfBarks (переменная типа int).

void bark(int numOfBarks) {


Используем параметр
while (numOfBarks > 0 ) { ■У numOf Barks в качестве
переменной внутри
System.out.println("Гав") ; метода.
numOfBarks - numOfBarks - 1;
}
}
104 глава 4
Методы содержат переменные экземпляра

Ъы можете получать значения обратно


из метода
М етоды могут возвращ ать значения. Каждый метод объявляется
с указанием типа возвращаемого значения, но до сих пор в этом
качестве мы использовали только тип void; то есть метод ничего
не отдавал.
Какая прелесть!..
v o i d g o () { Но это не совсем
} то, что я ожидала.
М ож но объявить метод, указав конкретный тип значения,
возвращ аемого вызывающ ему коду:
i n t g i v e S e c r e t () {
retu rn 42;

}
Если вы объявили метод, который возвращ ает
значение, то обязаны вернуть значение указан­
ного типа (и л и совместимое с ним ). М ы вер­
немся к этому в главах 7 и 8, когда будем
изучать полиморфизм.

Ч то бы вы ии пообе­
щ али, вам лучш е это
вернуть!

К ом пилятор н е поз& э/м п &ЛМ £еркущЬ ^ндЧекие

вы здесь ► 105
Множественные аргументы

0ы можете передать &метоЭ


сразу несколько значении
М етоды могут содержать несколько параметров. О б ъ ­
являем ы е параметры и передаваемые аргументы нуж но
разделять запяты м и. Что еще более важно, если метод
имеет параметры, то необходимо передавать ему аргум ен­
ты соответствую щ его типа и в правильном порядке.

#ы зов м е то да с двумя пар ам етра м и и передача


ему дв ух аргум ентов.
v o i d g o () {

T e s t S t u f f t = new T e s t S t u f f ( ) ;
t . taJceTwo

v o i d t a k e T w o ( in t x , i n t y ) {

in t z = x + y;
S y s t e m . o u t . p r i n t I n ("Сумма р а в н а " + z ) ;

М ож но п е р е да в а ть переменные в м етод, если их


ти пы со в п а д а ю т с типам и п а р а м е тр о в .

v o i d g o () { np3*P«J

i n t f 00 = 7 ;
3 n * 4 e t' wSLJ fl
in t bar = 3;
t.t a k e T w o (f o o , b a r)

v o i d t a k e T w o ( in t x , in t y) { ЗИЛЧ^?е? е ЪЭ™
in t z = x + y;
+ z) ;
JПере/леИнЬ
ku M

Гаo. U r tdkeTv/o.
-oo **
S y s t e m . o u t . p r i n t I n ("T o t a l i s
/летп°Э
u x V f e3 d 4 u
}
106 глава 4
Методы содержат переменные экземпляра

Java бее передается по значению.

Имеется &виду, что значение


копируется при передаче

О бъявляем целочисленную
in t х = 7 переменную и присваиваем ей
значение 7. Последовательность
битов для числа 7 отправляется
в переменную х.

v o id g o ( in t z ) { © сОбъявляем метод
целочисленным
параметром z.

К°Чи%
Вызываем метод до(),
передавая ему в качестве
аргумента переменную х.
Биты из х копируются
и помещаются в z.

Изменяем значение z внутри


•fa s* О метода. Оно не изменилось!
Аргумент, ставший параме­
тром z, — это всего лишь
копия х .
v o id g o ( in t z ) {
Метод не может изменить
z = 0; биты, хранящиеся в програм­
ме (в виде переменной х ), из
> которой он был вызван.

вы здесь ► 107
Аргументы и возвращаемые значения

Э то не а
Напоминание: Java
глупые Вопросы
заботится о типах!
Г • происходит, если аргумент, который вы хотите
Что
передать, представляет собой объект, а не примитив? Нельзя вернуть объект Giraffe
(жираф), если объявленный тип
о-• Это мы рассмотрим в следующих главах, но ответ возвращаемого значения —
вам уже известен. В Java все передается по значению. Все. Rabbit (кролик). Тот же принцип
Но... значение — это биты внутри переменной. Помните, работает с параметрами.
что вы не помещаете объекты в переменные; перемен­ Вы не можете передать
ная — это дистанционный пульт управления, или ссылка
Giraffe в метод, который
на объект. Таким образом, если вы передаете в метод
ссылку на объект, то тем самым передаете копию пульта
принимает объекты типа Rabbit.
для управления объектом. Оставайтесь с нами, и вы узнае­
те еще много интересного на эту тему.
----------КЛЮЧЕВЫЕ МОМЕНТЫ --------------
Может ли метод объявить несколько возвраща­
емых значений? Есть ли способ вернуть их одновременно? ■ Классы определяют, что объект знает и что
он умеет.
■ Информация, которой объект владеет, —
^ • Метод может объявить только одно возвраща­ это переменные экземпляра (состояние).
емое значение. Но если нужно вернуть, скажем, три ■ Действия, которые объект может выпол­
целочисленных значения, это можно сделать с помощью нять, — это его методы (поведение).
массива. Поместите числа в массив и верните их. С воз­
вращением значений разного типа все обстоит несколько ■ Методы могут использовать значения пе­
сложнее — об этом мы поговорим в следующей главе, ременных экземпляра, поэтому объекты
одного типа могут вести себя по-разному.
когда речь пойдет об ArrayList.
■ Методы могут содержать параметры, то
есть разрешено передавать им одно или
Должен ли я возвращать тот самый тип, который несколько значений.
указал при объявлении? ■ Количество и тип передаваемых значений
должны соответствовать параметрам, объ­
О-
^ • Разрешено вернуть любое значение, которое
явленным для метода (включая порядок их
следования).
можно неявно привести к этому типу. Поэтому вы можете
вернуть byte там, где ожидается int. Вызывающему коду • Значения, принимаемые и возвращаемые
все равно, так как значения byte отлично согласуются методом, могут быть неявно приведены
с типом int, который применяется для присваивания ре­ к более вместительному типу (или явно при­
зультата. Если объявленный тип меньше, чем тот, который ведены к менее вместительному).
вы пытаетесь вернуть, необходимо использовать явное ■ Значения, передаваемые в метод в каче­
приведение. стве аргументов, могут быть литералами
(2, 'с' и т. д.) или переменными тех типов,
фх*-• Обязательно ли что-то делать со значением,
которые были объявлены для параметров
(например, переменная х , которая имеет
которое возвращает метод? Можно ли его просто про­ тип int). Есть и другие объекты, которые
игнорировать? можно передавать в качестве аргументов,
но об этом мы поговорим позже.
■ Для метода должен быть объявлен тип
• Java не требует, чтобы вы подтверждали получение
возвращаемого значения. Тип void говорит
возвращаемого значения. Возможно, вам придется вы­ о том. что метод ничего не возвращает.
звать метод, который что-то возвращает, даже если вас не
интересует его значение. В этом случае метод вызывается ■ Если объявленный для метода тип возвра­
ради работы, которую он проделывает внутри себя, а не щаемого значения не равен void, то этот
ради возвращаемого значения. В языке Java не обязательно метод должен вернуть значение, совмести­
мое с указанным типом.
присваивать или использовать возвращенное значение.

108 глава 4
Методы содержат переменные экземпляра

Разные трюки с параметрами


и возвращаемыми значениями
Теперь, когда вы увидели, как работают параметры
и возвращаемые значения, пришло время найти им
достойное применение: рассмотрим геттеры и сеттеры.
В других источниках встречаются названия accessors
и mutatms. Можете называть их так, если угодно,
но именно термины «геттеры» и «сеттеры» хорошо
вписываются в соглашение по именованию, принятое Ъ Я лкущ эт и
getBrand()
с о г л а с н а я oS
в Java, поэтому мы будем использовать эти слова.
setBrandO ^еко& нии, е й
Геттеры и сеттеры позволяют получать и устанавли­ getNumOfPickupsf)
вать значения. Как правило, это значения переменных
setNumOfPickupsO
« ® Г &ет|есЬ
экземпляра. Главная задача геттера — вернуть значение
getRockStarUsesitO
(по аналогии с возвращаемым значением). Вероятно,
вы уже не удивитесь тому, что сеттеры принимают ар­ setRockStarllsesItO
гумент и устанавливают его значение для переменной
экземпляра.

class ElectricGuitar {

String brand;
int numOfPickups;
boolean rockStarUseelt;

String getBrand<) {
return brand;
}

void setBrand(String aBrand) {


brand = aBrand;
}

int getNumOfPickups() (
return numOfPickups;
}

void setHumOfPickups(int num) (


numOfPickups — num;
>

boolean getRockStarUsesIt() {
return rockStarUsesIt;
)

void setRockStarUsesIt(boolean yesOrNo) {


rockStarUsesIt = yesOrNo;
>
J вы здесь ► 109
Опытные разработчики используют инкапсуляцию

Инкапсуляция
Игнорируя ее, &ырискуете £ыть
осмеянными
Д о этого знаменательного момента мы
придерживались одного из самых неесте­
ственных стилей в ООП.
В чем же мы провинились?
Мы открыли наши данные!
Вот так мы насвистываем себе что-то под
нос, не заботясь о том, что наши данные
бришены на произвол судьбы и любой
может их увидеть и даже потрогать.
Вы уже должны были ощутить смутную
тревогу от осознания того, что ваши
переменные экземпляра открыты всем
подряд.
Открыты — значит доступны при
использовании оператора «точка», как
показано ниже:
th e C a t. h e ig h t = 27;
Представьте, что любой человек может
использовать пульт управления, чтобы
изменить поле size нашего объекта Cat.
Попав в руки не того человека, ссылоч­
ная переменная (пульт управления)
может превратиться в опасное оружие.
Этого не должно произойти.
Заставляя*"*
ОТ!
t h e C a t . h e ig h t = 0 ; ^ о эк ^ 3^ . g^evceHUU.
9о ^ с ^ Ы
p u b lic v o id s e t H e ig h t ( in t h t) {
Это будет большой ошибкой. Н еобхо­
димо создать методы-сеттеры для всех if ( h t > 9) {
переменных экземпляра и найти способ h e ig h t = h t;
заставить весь остальной код обращаться
}
к ним именно так, а не напрямую.
) •C S S '
Поля

110 глава 4
Методы содержат переменные экземпляра

Прячем Таимые Р А Э О Е л А Ч ЁЯЙ И Б


Н а самом деле можно легко
уйти от реализации, которая
ЯЗЫКА JAVA
Интервью этой недели:
провоцирует прием плохих Непредвзятый взгляд на инкапсуляцию
данных, к подходу, защ ищ а­ глазами Объекта.
ющему ваши поля и учиты ­
Hearfirst: Чем так важна инкапсуляция?
вающему ваше право вносить
изм енения спустя некоторое Объект: Знаеге, иногда человеку спится, что он выступает перед полным задом
людей и внезапно осознает, что голый.
время.
Headfirst: Да, нам тоже такоеснилось. Значит, вы чувствуете себя голым. Но есть
Н о как именно спрятать лив этом какая-то опасность, кроме риска быть обнаженным?
данны е? Это можно сделать Объект: Есть ли какая-то опасность ? (Смеется.) Эй, коллеги-экземпляры,
с помощью м одификаторов слышали, как он спросил: «Есть ли какая-т о опасност ь?» (Падает на пол от
public и private. С первым вы смеха.)
уж е знакомы , так как исполь­ Headfirst: Что в этом смешного? По-моему, это вполне корректный вопрос.
зовали его в каждом главном Объект: Ладно, я объясню. Это... (Опять взрывается от смеха, не может остано­
методе. виться.)
Headfirst: Может, вам что-то принести? Воды, например?
Первое правило и нкапсу­
Объект: Ух! Вот это да Нет, я в порядке, правда Попытаюсь быть серьезным.
ляции, которое опирается
Глубокий вдох. Хорошо, приступим.
на опы т многих программи­
Headfirst: Итак, от чего же вас защищает инкапсуляция?
стов, гласит (все оговорки,
Объект: Она создает защитный барьер вокруг моих переменных экземпляра, по­
присущ ие таким правилам,
этому никто не сможет передать им, скажем, что-то неподходящее.
остаю тся в силе): помечайте
Headfirst: Можете привести пример?
свои переменны е экзем п л я­
Объект: Большинство переменных экземпляра создаются с расчетом на то, что
ра модиф икатором private,
их значения будут ограничены определенными рамками. Представьте, сколько
добавляя публичны е (public) вещей сломается, если будут разрешены отрицательные значения. Количест во
геттеры и сеттеры дл я конт­ уборных в офисе. Скорость самолета. Дни рождения. Вес штанги. Телефонные
роля за доступом. П олучив номера. Мощность микроволновой печи.
больш е навыков в проекти ­ Headfirst: Я понимаю, что вы имеете* в виду. Как же инкапсуляция помогает
ровании и кодировании на установить эти рамки?
язы ке Java, вы, вероятно, Объект: Она вынуждает остальной код использовать сеттеры. В таком случае
начнете делать это немного метод-сеттер может проверить параметр и решить, подходит ли он. Возможно,
иначе, но пока такой подход метод отвергнет его и на этом все закончится, а может, будет сгенерировано
вас обезопасит. исключение (например, если номер социального страхования в профамме для
работы с кредитными картами равен null) или параметр будет округлен до ми­
нимально допустимого значения. Суть в том, что внутри сеттера вы можете де­
лать все что угодно, тогда как при наличии публичных переменных экземпляра
вы не можете сделать ничего.
Headfirst: По иногда мне попадаются сеттеры, которые просто устанавливают
значения, ничего не проверяя. Будет ли такой сеттер лишним, если у вас есть
переменная экземплярабез рамок? Не повлияет ли это на производительность?
Объект: Смысл сеттеров (и геттеров тоже) в том, что позже можно передумать
и что-то поменять, но при этом не придется нарушать чужой код\ Пред­
ставьте, что половина сотрудников компании используют ваш класс с его пу­
«К сожалению, Билл забыл бличными переменными экземпляра, и однажды вы внезапно понимаете: «Ой,
w с этим значением можно сделать то, чего я не предусмотрел. Заменю-ка я его
инкапсулировать свои класс
сеттером». В итоге вы сломаете весь чужой код. Самое замечательное в инкап-
Cat и получил плоскую
суляци и то, что вы всегда можете передумат ь ,и из-заэтого 11икто не пострадает.
кошку».
Выгода же от непосредственного использования значений слишком несущест­
(Было подслушано возле кулера венна и проявляется (если такое вообгце происходит) очень редко.
с водой.)
вы здесь > 111
Как себя ведут объекты

Инкапсуляция class GoodDog {


на примере I
GoodDog
private int size;
класса (joocfPog size

public int getSize() (


getSize()
return size;
setSize()
bark()

public void setSize(int s) { ----—--------- щ


----,--
У Х **?** size = s;
УЛb&S*
}

void bark О {
Д ^ж е кесМотпрЯ Kd к\о. ^П°
if (size > 60) (
^ о я м о ж н о стщ е й . o k п о л е з е н . тт\
System.out.println("Гав Гав!");
KdK п о зво ляем ^ к е и ш е м
} else if (size > 14) {
Ч^о-тпо поМекЯтпЬ. froЖКО
в е р к у ч Ь с Я К ЭЩОМ>| №V\o3y System.out.println("Вуф Вуф!");
и с д е л г ф е го ^ о п а с н е е , } else {
5(лстт\рее и Л^Чше. System.out.println("Тяф Тяф!");
)
}
}

class GoodDogTestDrive {

public static void main (String[] args) {


GoodDog one = new GoodDog ();
one.setSize(70);
GoodDog two = new GoodDog ();
two.setSize(8);
System.out.println("Первая собака: " + one.getSize())
System.out.printIn("Вторая собака: + two.getSize());
one.bark();
two.bark();
}
}

112 глава 4
Методы содержат переменные экземпляра

Как се^я ведут объекты


внутри массива
Как и лю бы е другие элементы. Единственное
отличие заклю чается в способе доступа к ним.
Д ругим и словами, важно, как вы получаете пульт
управления. П опы таемся вы звать методы из объ­
ектов Dog, которы е находятся внутри массива.

Объявляем и создаем массив


О для хранения семи ссылок
типа Dog.
D o g [] p e t s ;
p e t s = new D o g [ 7 ] ;

Объект массива типа bog (Dog[])


Dog[]

Создаем два новых объекта


О Dog и присваиваем их двум
первым элементам массива.
p e ts[0 ] = new D o g () ;
p e ts [l] = new D o g ( ) ;

О Вызываем методы из
объектов Dog.
p e t s [ 0 ] . s e t S i z e (3 0 ) ;
in t x = p e t s [ 0 ] .g e tS iz e ();
p e t s [ 1 ] . s e t S i z e (8) ;

Объект массива типа Dog (Dog[])


Bog[]
вы здесь ► 113
Инициализация переменных экземпляра

Объявление и инициализация
переменных экземпляра
Вы уж е знаете, что при объявлении переменны х необходимо
указы вать их имя и тип: Переменны е
in t s iz e ; экзем пляра, всегда
S t r i n g nam e; получаю т значения
по умолчанию .
Вы такж е знаете, что одновременно с этим мож но и н и ц и ал и зи ­
ровать переменную (присвоить ей значение):
Если вы явно
не присвоите
in t s iz e = 420;
S t r i n g name = "D onny";
переменной
значение или не
Н о что получится, если вы вы зовете геттер, не и н и ц и али зи ро­ вы зовете сеттер ,
вав соответствую щ ую переменную экзем п ляра? И ны м и слова­ она все равно будет
ми, какое значение переменная экзем п ляра содерж ит до своей хранить значение!
и ни ц и али зац и и ?
Целые О
c l a s s P oorD og { 0 § ъ * е м е * 9 ее
С плавающей точкой 0.0
p r i v a t e i n t size;
Булевые false
p r i v a t e S t r i n g nam e; n,i
@еркутг\ Этщи Ссылки null
p u b l i c i n t g e t S i z e () {
retu r n s i z e ; / J
) b.
p u b l i c S t r i n g g e tN a m e () {
r e t u r n nam e;
}

% java PoorDogTestDrive
Размер собаки — 0 Z Z *** 0. ЪоЬ» - f i t * a “ OOD
n рис&ил&Де^сЯ ци
Имя собаки — null у ч е н и е n u « го в о р и т о ц о А 4m ° х у Л т W

114 глава 4 Ссылка ecmb. да нет объекта-


Методы содержат переменные экземпляра

Разница между переменными экземпляра


и локальными переменными
Локальны е пере­
£ | Переменные экземпляра объявляются менные не содержат
внутри класса, но за пределами метода. значение по умол­
чанию! Компилятор
class Horse { будет возмущаться,
private double h e ig h t = 15.2; если вы попытае­
private String b re e d ;
// еще код...
тесь использовать
) локальную перемен­
ную до того, как ини­
£>% Локальные переменные объявляются циализируете ее.
внутри метода.
class AddThing { Э т о не
int а; глупые (опросы
int b = 12;

Я Как работают правила о ло­


public int add() { кальных переменных по отноше­
int t o t a l = a + b; нию к параметрам методов?
return total;
} Параметры методов фактиче­
} ски ничем не отличаются от локаль­
ных переменных — они объявлены
внутри метода (формально они
Локальные переменные перед объявлены в списке аргументов
использованием нужно инициализировать! метода, а не в его теле, но являются
локальными переменными, а не пе­
class Foo { He о к о /л л аЛ ^ г ^ сЯ - ременными экземпляра). Однако они
public void g o () { оЪЪ9<Ш> * всегда содержат значения, поэтому
int §е ч зн ач ен и я, но KdK вы никогда не получите от компиля­
тора ошибку, в которой говорится,
int z = x + 3; ТОЛЬКО что параметр не инициализирован.
) ~
'"его исп°>пЬзо8ат1\Ь, Если вы попытаетесь вызвать ме­
} ко/^иЛЯтпор соаоетг\ с \}Md. тод, не передав ему необходимые
аргументы, компилятор выдаст вам
другую ошибку. Таким образом, па­
раметры всегда инициализированы,
так как компилятор гарантирует, что
методы вызываются с аргументами,
совпадающими с объявленными для
них параметрами. Таким образом, ар­
гументы присваиваются параметрам
автоматически.
вы здесь » 115
Равенство объектов

Срз&ии&зем переменные Используйте опе­


(примитивы или ссылки) ратор ==, чтобы
сравнить примити­
И ногда нуж но узнать, одинаковы ли два примит ива. Э то довольно вы или проверить,
просто сделать, используя оператор ==. П орой разработчика интересу­ ссылаются ли пе­
ет, указы ваю т л и две ссы лки на один и тот же объект в куче. Это тож е ременные на одни
легко вы яснить благодаря тому ж е оператору ==. Н о иногда нуж но м тот же объект.
узнать, идентичны ли два объекта. И для этого понадобится метод Используйте метод
equals ( ) . И дентичность (или эквивалентность) объектов зави си т от
equalsO для провер­
их типа. К примеру, если два объекта типа String содерж ат оди нако­ ки идентичности
вы е сим волы (скаж ем, с л о ю « п р о в о р н ы й » ), они явн о эквивалентны , двух разны х объек­
несмотря на то что представляю т два разны х объекта в куче. Н о как
насчет ти п а Dog? Будете ли вы рассм атривать два объекта этого типа
тов.
как эквивалентны е, если им посчастливилось иметь одинаковы е значе­ Например, можно про­
ния переменны х si ze и weight? В ряд ли. Т аки м образом, два объекта верить два объекта типа
String, содержащих оди­
долж ны считаться эквивалентны м и, если это имеет смысл д л я конкрет­ наковую последователь­
ного типа. К идее эквивалентности объектов мы вернемся в следующ их ность символов.
главах (и в П рилож ении Б ), а пока вы долж ны четко уяснить, что опе­
ратор == используется только для сравнения битов в двух переменных.
С оверш енно не важно, что эти биты собой представляю т. О ни либо
одинаковы е, либо нет. Й
Для сравнения двух примитивов применяйте оператор ==
О ператор - - мож ет бы ть использован д л я сравнения двух переменных
лю бого типа — он просто проверяет на соответствие их биты.
В ы раж ение i f (а == Ь) {...} см отрит на биты внутри а и b и возвра­
щ ает true, если они совпадаю т (п ри этом размер переменны х не имеет
значения, начальны е нули не учиты ваю тся). , р.
in t а - 3; * п е р е л е й ^ Г .о Л
b y te Ь = 3; 5оЛЬШе к у в й . ™ ЗЭесЬ Э1Г,° №
i f (а = = Ь) { // tr u e } иМеетп значения. byte
Чтобы проверить, идентичны ли две ссылки (ссылаются ли ft
они на один объект в куче), используйте (итератор ==
суг)Ь
П омните, оператора == интересует только последовательность битов
в переменной. Это правило работает как для прим итивов, так и для « * * £ вил
°0е,
ссылок. Т аки м образом, оператор == возвращ ает true, если ссы лочны е г**р
Vyjjo'
переменны е указы ваю т на один и тот же объект! В данном случае мы не
знаем, какие именно биты там содерж атся (эта инф орм ация спрятана от
нас из-за особенностей JV M ), но нам точно известно, что две ссылки на
один объект будут хранит ь одинаковые данные.
T o o а = new F oo ( ) ;
F oo b = new F oo () ;
F oo с = a;
if (а = = Ь) { // fa ls e }
if (а == с) { // tr u e } cx - - с (зернект\ t r u e .
if (Ь == с) { // fa ls e ) I
<X == k вернетп fd jfse .
116 глава 4
Методы содержат переменные экземпляра

Я всегда делаю V
свои переменные
закрытыми. Если вы
хотите их увидеть,
придется поговорить
с моими методами. Псрометр*1
«epee*»1*4
! no
T.omuiii
етго

Прикрепи

Збе у пп зн ачени ю - -
n epeS aeLlJb
Зн ачи т, копируем -
лучше? Попробуй"2-3а1
В ы моле У оруЮстрокуtB

Наточите с&ой кз| -гг-»—*^


int a = calcArea(7 , 12);
Что допустим о?
short с = 7 ;
Ниже приведен метод. Какие
его вызовы, представленные calcArea(с,15);
справа, разрешены?
int d = calcArea(57);
Установите напротив правиль­
c a lc A re a ( 2 ,3 );
ного вызова флажок (некото­
рые выражения использую тся long t = 4 2 ;
для присвоения значений,
int f = calcArea(t,17);
передаваемых в дальнейшем
в м етод). int g = calcArea();
int calcArea(int height, int width) { calcArea();
return height * width;
byte h = calcArea(4 ,20);
) int j = calcArea(2 ,3 ,5);

вы здесь ► 117
Упражнение, поработайте компилятором

ражнение Поработый/Пъе Комщцятьором


£ а Я ^ Ы й > <JaVa-<|>aaA Ha э т ь о а
стк-раниде — ц о дп о и ен н ы й а с Х о ^ н а К .
Ф а т а за д а ч а — upatfuJSopaikbc.fl
К о м ц а д я ть о р о м и, о ц р е ^ е д а т ь ь , £ с е д а
ф а а д ы сК о м ц а д а р /ю т ь с^ .
Б е д а К ом цаддиАЯ
нс с м о ж е м цроаньи,
/ с п е ш н о , к а к $ы а /
a c u p a JJa t u ? Д “ се д а она
Uc %с c K o M u a A a {/io D i,c j?f
К а К а м Sytfcyh, р с з / д ь т м и ь ?

А В

class ХСору { class Clock {


String time;
public static void main(String [] args) (
void setTime(String t) (
int orig = 42;
time = t;
XCopy x = new XCopyO; }

int у = x.go(orig); void getTimeO {


return time;
System.out.println(orig + " " + y);
}
}
)
int go(int arg) {
class ClockTestDrive (
arg = arg * 2; public static void main(String [] args) {

return arg; Clock c = new Clock();


}
}
c.setTime("1245");
String tod = c.getTime();
System.out.println("время: " + tod);
}

118 глава 4
Упражнение: кто я такой?

Команда звезд из мира Java хочет сыграть с вами в игру «Кто


я такой?». Они дают вам подсказку, и вы пытаетесь угадать их
имена, основываясь на полученной информации. Считайте, что
они никогда не врут. Если они говорят что-нибудь подходящее
сразу для нескольких участников, то записывайте всех, к кому
применимо данное утверждение. Заполните пустые строки
именами одного или нескольких участников рядом с утвержде­
ниями.
Сегодня участвуют:
переменная экземпляра, аргумент, return, геттер,
сеттер, инкапсуляция, public, private, передача
по значению, метод.

Класс может содержать лишь один такой элемент. ______________________________________

Метод может хранить только один такой элемент. ____________________________________ _

Это может быть неявно приведено к другому т и п у . ______________________________________

Я предпочитаю, чтобы мои переменные экземпляра


были з а к р ы т ы м и . ______________________________________

Это означает «сделать копию». ____________________________ __ -...—

Только сеттер должен изменять это. ______________________________________

Метод может иметь много таких элементов. ______________________________________

Я что-то возвращаю, и это ясно из моего названия. ______________________________________

Я не должен использоваться вместе с переменными


экземпляра. ---------------------------------------

У меня может быть много аргументов. ---------------------------------------

По определению я принимаю один аргумент. ---------------------------------------

Это помогает создавать инкапсуляцию. ---------------------------------------

Я всегда беру на борт только одного пассажира. ---------------------------------------

вы здесь > 119


Смешанные сообщения

^рги еш атгы е
со о о щ е н и #

Справа приведена небольшая Java-


public class Mix4 {
программа. Два ее блока потерялись.
Ваша задача — сопоставить варианты int counter = 0;
блоков кода (ниж е)с результатами вы­ public static void main(String [] args) {
вода, которые вы увидите, если эти блоки int count = 0;
будут добавлены.
Mix4 [] m4a =new Mix4[20];
Не все строки с результатами будут int x = 0;
использованы, а некоторые пригодятся
несколько раз. Соедините линиями вари­ while ( {
анты кода с соответствующим результатом
m4a[x] = new M i x 4 ();
в командной строке.
m4a[x].counter = m4a[x].counter + 1;
count = count + 1;
count = count + m4a[x].maybeNew(x);
x = x + 1;
}
System.out.println(count + " "
+ m 4 a [1].counter);
Варианты Возможный
}
кода: результат:

х < 9 public int maybeNew(int index) (

index < 5
if ( Г” — П {
Mix4 m4 = new Mix4();
m4.counter = m4.counter + 1;
х < 20
return 1;

index < 5 }
return 0;
}
25 'i
X < 7 }

in d e x < 7 7 7

ap-peV ; ’
20 1

20 5

120 глава 4
Головоломка у бассейна

public class Puzzle4 {


public static void main(String [] args) {

int у = 1;
int x = 0;
Г о л о в о л о м к а / б ассей н а int result = 0;
Ваша задача — взять фрагмен­ while (x < 6) {
ты кода со дна бассейна и за­
менить ими пропущенные
участки программы. Нельзя у = у * 10;
использовать один фрагмент
несколько раз, и не все из них }
вам пригодятся. Ваша цель — x = б;
создать класс, который скомпи­ while (x > 0) {
л и р у е м , запустится и выведет
приведенный ниже текст. result = result + _____ ____
}
System.out.println("Результат + result);
}
}
class __________ {
int ivar;
______ _____ doStuff(int > (
if (ivar > 100) {
return ________________
) else {
return ________________
)
)
)

Примечание: каждый
фрагмент кода из бассей­
на может быть использо­
ван только один раз!
doStuff(x);
obs.doStuff(x);
obs[x].doStuff(factor)
ivar = x;
obs[x] doStuff(x); ivar + factor;
J r obs.ivar = x; Puzzle4
ivar* (2 + factor)
obslx].ivar = x; ivar Puzzle4b int
ivar * (5 - factor);
obs[x].ivar = y, factor Puzzie4b() short
ivar * factor;
Puzzle4 [ ] obs = new Puzzle4[6]; public obs [x] = new Puzzle4b(x),
private x =x + 1
Puzzle4b [ ] obs = new Puzzle4b[6]; obs [ ] = new Puzzle4b( );
Puzzle4b [ ] obs = new Puzzle4[6]; obs [x] = new Puzzle4b( );
obs = new Puzzle4b(); ^

вы здесь * 121
Пятиминутный детектив
Время перемен в Стим Сити
Когда Бьюкенен направил свой пистолет в сторону Джайя, тот застыл. Джай знал, что
глупость Бьюкенена могла сравниться только с его уродством, и не хотел нервировать
здоровяка. Бьюкенен вызвал Джайя в офис своего начальника, но Джай не сделал ни­
чего плохого (по крайней мере за последнее время), поэтому он решил, что небольшая
беседа с боссом Бьюкенена, господином Леверелом, не сулит больших неприятностей...
В последнее время он продал приличное количество нейростимуляторов, и надеялся,
что Леверел будет доволен. Работа подпольным распространителем препаратов не при­
носила много денег, но была спокойной. Большинство клиентов, с которыми он имел
дело, спустя некоторое время оказывались на мели и возвращались к прежней жизни,
разве что после этого они были чуть менее сосредоточенными, чем раньше.
«Офис» Леверела на первый взгляд представлял собой потрепанный автомобиль, но
как только Бьюкенен затолкал его внутрь, Джай увидел, что эта колымага тюнинго-
вана настолько, чтобы обеспечить скорость и безопасность, какие мог себе позволить
такой мелкий начальник, как Леверел. «Джай, мальчик мой, — выдавил из себя Л е­
верел, — рад снова тебя видеть». «Взаимно, я полагаю, — ответил Джай, чувствуя
неладное. — Мы вроде в расчете, или я что-то упустил?» «Ха! С виду нее выгля­
дит неплохо, твой оборот увеличился, но недавно я наткнулся на, скажем так,
небольшую брешь...» — сказал Леверел.
Р V v Джай непроизвольно вздрогнул — в свое время он был одним из лучших
1<^1ьЦ'Ми>1|У'У1гЛЬк i хакеров-взломщиков. Каждый раз, когда кто-нибудь умудрялся сломать
'' защиту одного из уличных авторитетов, Джай получал порцию ненужного
ему внимания. «Да ладно, это же я, дружище, — залепетал Джан, - я завя­
зал с хакерством. Я просто оставил это позади и занимаюсь своим бизнесом». «Да-да, —
улыбнулся Леверел, — не сомневаюсь, что на этот раз ты чист, но я понесу большие
убытки, пока новый хакер не исчезнет!» «Может быть, ты лучше высадишь меня здесь,
и я продам еще парочку “упаковок” для тебя, прежде чем закончится мой рабочий
день», — предложил Джай.
«Боюсь, все не так просто, Джай. Бьюкенен только что рассказал мне, чем ты приторго­
вываешь на своем углу», — вкрадчиво произнес Леверел. «Нейролептики? Я немного
с ними побаловался, что с того?» — ответил Джай, испытывая легкую тошноту. «С по­
мощью нейролептиков я сообщаю клиентам, где будет следующая точка распростране­
ния, — пояснил Леверел. — Проблема в том, что некоторые наркоманы держатся доста­
точно долго, чтобы понять, как пролезть в базу данных моего склада». «Нужно, чтобы
такой смышленый парень, как ты, Джай, взглянул на мой класс StimDrop — методы,
переменные экземпляра и т. д. — и выяснил, как они проникают внутрь. Это должно...»
«Эй! — крикнул Бьюкенен. — Я не хочу, чтобы такие грязные хакеры, как Джай, кру­
тились возле моего кода!» «Спокойно, начальник, — Джай понял, что у него появился
шанс. — Я уверен, что ты проделал первоклассную работу со своими модификаторами
до...» «Молчи, бездельник! — заорал Бьюкенен. — Все методы для клиентов я оставил
публичными, чтобы те могли заходить па сайт, но все важные методы класса, работа­
ющего со складскими данными, я сделал закрытыми. Никто не может получить доступ
к ним извне, приятель, никто!»
«Думаю, я могу найти твою утечку, Леверел. Что скажешь, если мы высадим Бьюке­
нена здесь на углу и прокатимся вокруг квартала?» — предложил Джай. Бьюкенен
выхватил свой револьвер, но Леверел уж е прислонил дуло к его шее. «Оставь его, —
усмехнулся Леверел, — брось ствол и выходи, похоже, у нас с Джайем есть дела».

К акие подозрения возникли у Д ж ай я?


122 гла ва 4 Смог л и он вы б рат ься из м аш ины Л е в е р е л а целы м и н евредим ы м ?
Ответы

class Clock (
String time;
void setTime(String t) {
time = t;
в ,
String getTime() {
return time;
}
}

class ClockTestDrive {
public static void main(String [] args) {
Clock c = new Clock();
c. setTime{"1245");
String tod = c.getTimeO;
System.out.println("время: " + tod);
} _________________________________
А Класс XCopy компилируется и запускается ) Примечание: метод-
в первоначальном виде! Программный вывод: 42.84. геттер должен содержать
Помните, что Java передает параметры по значению в своем объявлении тип
(то есть путем копирования), переменная orig
возвращаемого значения.
не изменится в методе до().

К йы о jt т ы К о й ?
Класс может содержать лишь один такой элемент. П ерем ен н ы е экзем п ляра, геттер, сеттер, м етод,

Метод может хранить только один такой элемент. re tu rn

Это может быть неявно приведено кдругому типу. re tu rn , аргумент.

Я предпочитаю, чтобы мои переменные экземпляра были закрытыми. И нкапсуляция

Это означает «сделать копию». П еред ача по значению

Только сеттер должен изменять это. П ерем ен н ы е экзем п ляра.

Метод может иметь много таких элементов. Аргумент.

Я что-то возвращаю и это ясно из моего названия. Геттер.

Я не должен использоваться вместе с переменными экземпляра. public.

У меня может быть много аргументов. М етод.

По определению я принимаю один аргумент. Сеттер.

Это помогает создавать инкапсуляцию. Геттер, сеттер, public, p riv ate ,

Я всегда беру на борт только одного пассажира. re tu rn

вы здесь ► 123
Ответы

Оук^ст/кЫ на. голо#оАомКш

Разгадка пятиминутного детектива


Головоломка/ бассейна
public class Puzzled ( Джай знал, что Бьюкенен не самый смыш­
public static void main{String (] args) { леный парень на свете. Рассказывая о своем
Puzzle4b [ ] obs = new Puzzle4b[6]; коде, тот ни разу не упомянул переменные
int у - 1; экземпляра. Джай предположил, что, за­
int x = 0; щитив методы, Бьюкенен забыл пометить
int result = 0; переменные экземпляра модификатором
while (x < 6) ( p r i v a t e . Эта ошибка запросто могла стоить
obs[x] = new Puzzle4b(); Леверелу больших денег.
o b s[x]. ivar = y;
У = у * 10;
x = x 1;
} Смешанные
x = б;
еообъц ^н и #
while (x > 0) {
x = x - 1; Варианты Возможный
result = result + obs[x].doStuff(x); кода: результат:
}
System.o u t .println("результат" + result);
}
}
class Puzzle4b {
int ivar;
public int doStuff (int factor) {
if (ivar > 100) {
return ivar * factor;
) else {
return ivar * (5 - factor);
) Р езу л ь т ат;
) | File Edit Window Help fiellyFlop ~
% java Puzzle4
Результат 543345

х < 19

in d e x < 1

124 глава 4
5 Созд ани е программ

Особо мощные методы


Я могу
поднимать
щ т тяжелые объекты

Сделаем методы ещ е более мощными. Вы утке поработали с переменными,


несколькими объектами и написали небольшой код. Но для полноценной работы потребует­
ся больше инструментов. Например, операторы нужны для того, чтобы сделать нечто более
интересное, чем воспроизведение лая собаки или программа с циклами. Конечно, циклы
нужны, но не только такие простые, как while. Если вы на самом деле решительно настроены,
придется прибегнуть к циклам for. Они пригодятся для генерирования случайных чисел
и преобразования строк в тип int — поверьте, это будет интересно. Почему бы вам во
время учебы не создать что-нибудь настоящее, чтобы собственными глазами увидеть, как
с нуля пишутся (и тестируются) программы? Может быть, это будет игра вроде «Морского
боя». Тяжелая задача, поэтому на ее выполнение придется потратить две главы. В этой главе
мы рассмотрим упрощенную версию игры, а потом сделаем ее более мощной и интересной.

з т о новая глава > 125


Создание настоящей игры

Создадим аналог «Морского


£оя»: игра «Потопи с а й т »
Здесь вы будете играть против компью тера. О сновное
отличие от оригинального «М орского боя» состоит
в том, что тут не нуж но размещ ать свои корабли. Вме­ Вам предстоит создать
сто этого придется потопить корабли компью тера за игру «Потопи сайт» с доской
м иним альное количество ходов. 7x7 и тремя «сайтами »,
Кроме того, вы будете топить не корабли, а «сайты» каждый из которых за­
(повы ш ая тем самым свою бизнес-грамотность и о к у ­ нимает три ячейки.
ная расходы на эту книгу).
Цель: потопить все «сайты» компью тера за м и н им аль­
ное количество попыток. Вы будете получать баллы
в зависим ости от того, насколько хорош о играете. Фрагмент игрового диалога
Подготовка: при загрузке программы компью тер р аз­
File Edit Window Help Sell
м естит три «сайта» на виртуальной доске (7 x 7 ). После
этого вас попросят сделать первы й ход. % java DotComJBust

Как играть: вы пока не научились создавать G U I Сделайте ход АЗ


(граф ический пользовательский интерф ейс), поэтому Мимо
данная версия будет работать в командной строке.
Сделайте ход В2
К омпью тер предлож ит вам ввести предполагаемую
ячейку в виде АЗ, С5 и т. д. В ответ на это в командной Мимо
строке вы получите результат — ли бо «П опал», либо Сделайте ход 'С 4
«М имо», ли бо «Вы потопили Pets.com » (и л и лю бой
Мимо
другой «сайт», которы й вам посчастливилось потопить
в этот день). К ак только вы отправите на корм рыбам Сделайте ход Ц2
все три «сайта», игра заверш ится вы водом на экран Цопал
ваш его рейтинга. а
Д оска 7xсе к ц и я Сделайте хо д D3
Э ^о «яч ей ка» . Попал

А С д е л а й т е ход D4
. ’ -' . * ‘-у ' ‘-
1 '" Вы п о т о п и л и ' P e t s .c o m : (
В
Е Потопил
О
С U
rsi
. ^ „
1# >2
D Ф Ми м о
р « ts .c o < n
. .. Е Й Сделайте ход
Е
Попал
F С д е л а й т е ход
G
A s k M e .c o m
I-:— ; t- -
1

Н а ч и н а е м с я с к у т я , к а к A k tc c u ^ b i £ J a v a .
126 гла ва 5
Создание программ
# пер&ую очередь высокоуровневое
проектирование
Понятно, что нужны классы и методы, но каки­
ми они должны быть? Чтобы ответить на этот
вопрос, необходимо получить больше информа­
ции о том, как игра должна себя вести.
П реж де всего нужно определиться с игровы м
процессом. Рассм отрим общую идею.

оо Пользователь запускает игру.

Игра создает три «сай та».


Настройка
игры о
Игра размещает « сай ты » на П олучаем
виртуальной игровой доске. пользователь-

© Игра начинается.
Повторять следующие действия, пока
не останется ни одного «сайта».

П редлож ить пользователю

С А
сделать х о д (А 2 , СО и т. д.).

Проверить все «сай ты »


на попадание, промах
Удаляем
«сайт»

и потопление. Выбрать
подходящ ее действие:
е сли попадание — удалить __Ром5 onucta&iew,
ячейку (А2„ 0 4 и т. д.). Е с л и ^ -п^оЧк^ ветщ&пениЯ.
потопление — уд а ли ть «сай т».

© Игра заканчивается.
Показать пользователю
рейтинг, основываясь
на количестве попыток.

И так, вы получили представление о том, что


долж на делать программа. Д алее необходи­
мо вы яснить, какие д л я этого понадобятся
объекты. Д ум айте об этом, как Брэд, а не как
Л арри; в первую очередь сосредотачивайтесь
на э л е м е н т а х , из которы х состоит програм ­ Ухты! Настоящая
ма, а не на п р о ц е д у р а х. блок-схема.

вы здесь ► 127
Создание настоящей игры

Пла&иое Введение в игру


«Потопи са й т » Игра запускается и создает один
П охоже, потребуется минимум два класса — Game «сайт», присваивая ем у адрес из трех
и D otC om . Н о преж де чем написать полноценную игру, ячеек в ряду.
создадим ее упрощ енную версию. Э тим мы и займ емся Вместо А2, СА и подобных
в текущ ей главе, а полноценную версию оставим для обозначений положение сайта
главы 6. представлено числам и. Например,
местополож ение 1, 2, 3 показано на
В этой версии все просто. Вместо двум ерной сетки мы следую щ ей картинке:
будем использовать единственны й ряд. И вместо т рех
«сайтов» у нас будет только один.
Т ем не менее принцип игры остается тем же: нуж но со­ 1
здать экзем п ляр класса D otC om , присвоить ему поло­
ж ение где-нибудь в ряду, получить пользовательский Начинается игровой процесс.
ввод и, когда все три ячейки «сайта» будут поражены, © П редлагаем пользователю сде­
лать х о д , по сле чего проверяем,
закончить игру.
попал ли он в одну из трех ячеек
Упрощ енная версия дает SimpleDotUomuaiuii «сай та». Е с л и по пал, то ув е л и ­
хороший старт д л я создания чиваем значение переменной
полноценной игры. Создав numOf H its на 1.
что-то маленькое, позже можно
расш ирить и услож нить это. Игра завершается, если
В текущ ем варианте класс все три ячейки пораже­
ны (значение перемен­
игры не содерж ит переменных
ной numOf H its д о сти г­
экзем пляра, а весь игровой
л о 3 ). а пользователю
код находится в методе m ain(). сообщается, сколько
И ны м и словами, после запуска ходов ему потребова­
игры и вы зова главного метода лось для потопления
будет создан только один экзем ­ «сай та».
пляр класса D otC om , после чего
для него будет вы брано полож ение
(три последовательны е ячейки ви р­
туального ряда). Д алее программа предло­ Полная версия игрового диалога.
ж и т пользователю сделать ход, проверит его вариант, | hit' if.tiil V7»i';iJf.\v Hulj.- Гм;ч!|ov__
и предыдущ ие два действия станут повторяться, пока Ija v a Sim pleD otCom G am e
все три клетки не будут поражены.
Введите число 2
Н е забы вайте, что виртуальны й ряд остается вирт у­
Попал
альным, то есть не сущ ествует нигде в программе. П ока
игре и пользователю известно, что «сайт» спрятан Введите число 3

в трех последовательны х ячейках из семи возмож ны х Попал


(начиная с нулевой), ряд как таковой не нуж дается Введите число 4
в программном представлении. М ож ет возникнуть Мимо
соблазн создать массив и з семи элементов и п рисво­
Введите число 1
ить трем из них числа, представляю щ ие «сайт», но это
необязательно делать. Нужен массив, которы й хранит Потопил
лиш ь три клетки, занимаемы е «сайтом». Вам п о т р е б о в а л о с ь 4
попы ток(и)
128 глава 5
Создание программ

faw aSom xa класса кодз, которые мыизпишем


с)ля каждого класса:
К ак у каждого программиста, у вас, вероятно, есть
своя методология написания кода. Собственно, как
и у нас. С писок, приведенны й ниже, создан для того,
чтобы помочь вам увидеть и понять, о чем мы думали
при разработке класса. Н еобязательно использовать
такой подход при написании настоящ его кода. Н е­ Эта полоса будет размещена на следующих стра­
сомненно, на практике вы будете основы ваться на ницах, чтобы напоминать вам, над какой частью
собственных предпочтениях, требованиях проекта вы в данный момент работаете. Например, если
или работодателя. О днако перед вами простирается вы видите ее вверху страницы, это означает, что
обш ирное поле для действий. Н апример, когда мы со­ вы пишете псевдокод для класса SimpleDotCom.
здаем «учебный» класс на язы ке Java, обы чно делаем к
это так. Класс SimpleDotCom

□ Выясняем, что должен делать класс.


□ Перечисляем переменные экземпляра
и методы. Псевдокод
П Пишем псевдокод для методов (очень Алгоритм, который поможет вам сосредо­
точиться на логике, не вникая в синтаксис.
скоро вы увидите, о чем речь).
□ Пишем тестовый код для методов.
Тестовый код
□ Реализуем класс. Класс или метод, с помощью которого
можно проверять реальный код и подтвер­
□ Тестируем методы. ждать, что он работает правильно.
□ Отлаживаем и при необходимости кор­
ректируем. Реальный код
Непосредственная реализация класса. Это
□ Радуемся, что не нужно проверять рабочий код на языке Java.
нашу так называемую учебную програм­
му на реальных пользователях.
К
В ы п о л н я т ь : ■

С"- *: шт
. „ Сила К л а с с S im p le '» 0 * 0 " '
О написать псевдокод.

мозга П
О
„ а п и с а ть тестовы й коп:
написать окончательный Java-c -Д
Пора размять извилины.
Как решить, какой класс (или классы) со­
здавать в первуюочередь? С чего начать, К л а с с S ! m p .e D ° * C ol" ‘* , » e
если учитывать, что любая программа при­ D написать псевдокод.
личных размеров состоит из нескольких
п „описать тестовый *СЛ '
классов (мы предполагаем, что вы придер­
живаетесь объектно ориентированного D „ а окончательный Java-m fi
Q написать око
стиля и одинкласс у вас не выполняет
сразу несколько действий)?

вы здесь > 129


Создание настоящей игры

П севдокод ^TectOBwS
код

SimpleUotCom О знаком ивш ись с этим примером, вы поймете, как работает наш вариант
intf] Joe alion Cells псевдокода. Это что-то среднее между реальным кодом на язы к е Jav a и опи­
ini numQIHits санием класса на человеческом язы ке. Б ольш ая часть псевдокода содерж ит
три раздела: объявление переменны х экзем пляра, объявление методов, л о ги ­
String checkYourselKString guess) ка методов. И з этих трех составляю щ их наиболее важ на последняя, так как
void seiLocabonCeUs(im(| loc] в ней описы вается, что долж но произойти.

ОБЪЯВЛЯЕМ целочисленный массив для хранения адреса ячеек. Даем ему имя
locationCells.
ОБЪЯВЛЯЕМ переменную типа int для хранения количества попаданий. Называем
ее numOfHits и ПРИСВАИВАЕМ ей 0.

ОБЪЯВЛЯЕМ метод checkYourselfQ, который принимает ход пользователя в каче­


стве параметра String (1, З и т . д.), проверяет его и возвращает результат: «Попал»,
«Мимо» или «Потопил».
ОБЪЯВЛЯЕМ сеттер setLocationCells(). который принимает целочисленный массив
(хранящий адрес трех ячеек в виде переменных типа int — 2, 3, 4 и т. д.).

МЕТОД: String checkYourself(String userGuess)


ПОЛУЧАЕМ ход пользователя в виде строкового параметра.
ПРЕОБРАЗУЕМ полученные данные в тип int.
----ПОВТОРЯЕМ это с каждой ячейкой массива.
//СРАВНИВАЕМход пользователя с местоположением клетки.
----ЕСЛИ пользователь угадал,
ИНКРЕМЕНТИРУЕМ количество попаданий.
//ВЫЯСНЯЕМ, была ли это последняя ячейка.
----ЕСЛИ количество попаданий равно 3, ВОЗВРАЩАЕМ «Потопил».
ИНАЧЕ потопления не произошло, значит, ВОЗВРАЩАЕМ «Попал».
---- КОНЕЦ ВЕТВЛЕНИЯ
ИНАЧЕ пользователь не попал, значит, ВОЗВРАЩАЕМ «Мимо».
----КОНЕЦ ВЕТВЛЕНИЯ
----КОНЕЦ ПОВТОРЕНИЯ
КОНЕЦ МЕТОДА

МЕТОД: void setLocationCells(int[] cell Locations)


ПОЛУЧАЕМ адреса ячеек в виде параметра с целочисленным массивом.
ПРИСВАИВАЕМ полученный параметр полю, хранящему адреса ячеек.
КОНЕЦ МЕТОДА
гл а в а 5
Создание программ

Ох! Но минуту
мне показалось, что
З аписы ваем р еализац ию ты собираешься писать
м е то да не тестовый код.
Не пугай меня так
Теперь напишем настоящ ий кос) ч-— v больше. г~
и за ста в и м его р а б о та ть .

Н о прежде чем начать, перестра­


хуемся и напиш ем код для т ест и­
рования. Все верно, мы напишем
проверочны й код еще до того, как
у нас п оявится что проверять!
П редварительное создание тесто­
вого кода — одна из концепций
экстрем ального программиро­
вания (E xtrem e Program m ing,
или Х Р ) — позволяет упростить
(и ускорить) написание програм­
мы. Э то не значит, что вы д ол ж ­
ны использовать Х Р, но подход
с предварительны м написанием
тестов нам импонирует. Кроме
того, Х Р — это здорово звучит\

Э кстрем альное програм м и ровани е (ХР)


Экстремальное программирование — это но­ Придерживайтесь пошаговой циклической разра­
вое веяние в мире веб-технологий. Появившись ботки.
в конце 1990-х, эта концепция была опробована Не добавляйте в код элементы, которых нет в тех­
многими компаниями: от мелких магазинов с дву­ ническом задании (независимо от того, насколько
мя работниками до корпорации Ford. Экстремаль­ сильно вам хочется сделать это «на будущее»).
ное программирование часто рассматривается как
«подход, с которым программисты действительно В первую очередь пишите тестовый код.
хотят работать». Суть ХР — клиент всегда полу­ Никаких сверхурочных; используйте обычное рабо­
чает то, что хочет и когда хочет, даже если для чее время.
этого необходимо постфактум менять техническое Улучшайте код при каждом удобном случае.
задание.
Не выпускайте новую версию, пока она не пройдет
Экстремальное программирование основано на все тесты.
наборе проверенных правил и рекомендаций,
Устанавливайте реалистичные сроки, привязанные
которые дополняют друг друга, хотя многие люди
выбирают и адаптируют для себя только часть из к выпуску минорных версий.
них. Эти правила и рекомендации включают в себя Не усложняйте (принцип Keep it simple).
следующее. Разбивайте разработчиков на пары и постоянно
Вносите в новые версии небольшие изменения, но меняйте их местами, чтобы каждый знал о коде
делайте это часто. практически все.

вы здесь ► 131
Создание настоящей игры

1естовый код Зля класса SimplcPofCom


Нужно написать тестовый код, который позволит создать объект
Sim pleDotCom и запустить его методы. В данном случае нам
интересен только метод chackYourSelfO, но для его правильной
работы нам придется также реализовать метод setLocationCellsQ.
Внимательно изучите псевдокод для метода chackYourSelfO,
приведенный ниже. Здесь метод setLocationCells() — обычный
сеттер, поэтому мы не обращаем на него внимания. Однако в ре­
альном приложении может понадобиться более сложный метод
с необходимостью тестирования.
Теперь спросите себя: «Если метод checkYourSelf() уж е реализо­
ван, какой тестовый код я могу написать, чтобы убедиться в его
корректной работе?»

Исходя из эт о го псевдокода: Как происходит


тестирование.
МЕТОД: StringcheckYourself(StringuserGuess) 1. Создаем экземпляр клас­
са SimpleDotCom.
ПОЛУЧАЕМ ход пользователя в виде строкового параметра.
2. Присваиваем ему ме­
ПРЕОБРАЗУЕМ полученные данные в int.
стоположение (массив
ПОВТОРЯЕМ это с каждой ячейкой массива. из трех чисел, например
{2 ,3,4}).
/ / СРАВНИВАЕМ ход пользователя с адресом ячейки.
3. Создаем строку для пред­
ЕСЛИ ход пользователя совпал,
ставления хода пользова­
ИНКРЕМЕНТИРУЕМ количество попаданий. теля («2», «О» ит. д .).
//В Ы Я С Н Я Е М , была ли это последняя ячейка. 4. Вызываем метод
ЕСЛИ количество попаданий равно 3, ВОЗВРАЩАЕМ «Потопил». checkYourSelf(), переда­
вая ему вымышленный
ИНАЧЕ потопления не произошло, то ВОЗВРАЩАЕМ «Попал». ход пользователя.
КОНЕЦ ВЕТВЛЕНИЯ 5. Выводим на экран ре­
ИНАЧЕ пользователь не попал, ВОЗВРАЩАЕМ «Мимо». зультат, чтобы увидеть,
корректно ли сработал
КОНЕЦ ВЕТВЛЕНИЯ код («Пройден» или «Не­
КОНЕЦ ПОВТОРЕНИЯ удача»).
КОНЕЦ МЕТОДА

132 глава 5
Создание программ
П с е в д о к о д - i1hcfoeb*&
т
Тестовый кск) с)ля класса SimplePotCom
Э то не _
глупые I опросы public class SimpleDotComTestDrive {

• Может быть, я что-то упу­ public static void main (String!) args) { 1
стил, но объясните, как именно вы
тестируете элементы, которых даже SunpleDotCom dot = new SimpleDotCom(); <
не существует?

О;• Вы ничего не упустили. Мы ни­


когда и не говорили, что начинать нуж­ int[] locations = {2 ,3 ,4};
но с выполнения тестов; вы начинаете
с их написания. При создании тестового dot.setLocationCells(locations)
кода у вас нет ничего, на чем можно его
опробовать, так что вы, вероятно, не
*с«й*)д* 'e*)»lep
сумеете его скомпилировать, пока не
напишете формально работающую «за­
String userGuess = " 2 д<4&М XOQ o№ uM6HU
глушку», но это всегда будет приводить
Г.оЛЬЗО&ще/Л-
к провалу теста (например, возвращать
null). String result = dot.checkYourself(userGuess) ;
Г Ч ..
String testResult = "Неудача"; Метцос
Я все еще не понимаю, в чем cteckyourSeff()~'
суть. Почему бы не подождать, пока if (result.equals ("Попал") ) { e *yr!Ci С о уг ).
код будет написан, и только затем
добавлять тесты?
testResult = "Пройден";

О Тщательное обдумывание тесто­


вого кода (и его написания) помогает gee
более четко представить, какие дейст­
System.out.println(testResult);
вия требуются от метода.
После реализации метода вам останет­
ся только проверить его с помощью уже ?Р «°*9«и я ч е с *
готового тестового кода. Кроме того, вы ' « p o u je t» ш п
знаете, что если не напишете его сей­ ^пе^ь.Чц»),
час, то не напишете уже никогда. Всегда
найдется более интересное занятие. Наточите сбой карандаш
Старайтесь писать небольшой тесто­
вый код, после чего создавайте реа­ На нескольких следующих страницах мы реализуем класс
лизацию лишь в том объеме, который SimpleDotCom, а позже вернемся к тестовому классу. Взгляни­
позволит ей пройти этот тест. Затем те на тестовый код, приведенный выше. Как его можно допол­
напишите чуть больше тестового кода нить? Какие моменты, которые следовало бы проверить, в нем
и создайте новую реализацию для его упущены? Изложите свои идеи (или строки кода) здесь;
прохождения. На каждом этапе запу­
скаются все уже написанные тесты, по
этому вы всегда можете быть уверены,
что последние изменения не нарушают
код, протестированный ранее.
вы здесь > 133
Создание настоящей игры

Метой checkyouselfO
Не существует идеального перехода от псевдокода к коду на языке Java —
всегда будут вноситься некоторые изменения. Псевдокод позволил лучше по­
нять, что должен делать метод, и теперь нужно подобрать Java-код, с помощью
которого можно выразить, как ему это следует делать.
Посмотрите на этот код и подумайте, что бы вам хотелось в нем улучшить.
Числами обозначаются такие особенности синтаксиса и языка, с которыми
вы еще не знакомы. Они будут подробно разобраны на следующей странице.

ПОЛУЧАЕМ ход пользо­ p u b lic S t r in g c h e c k Y o u r s e lf ( S t r in g s t r in g G u e s s ) {


вателя ази де строково­
го параметра. © — J / P ^ W y e M TrjuT)
in t g u e ss = In t e g e r .p a r s e ln t ( s t r in g G u e s s ) ; n o t r in ^ e ir y t .
ПРЕОБРАЗУЕМ вспучен­
ные данные в ini. худ а е м Переменную для xp^ ie
S t r in g r e s u l t = -М и м о "; f ' «<Щ орЫ й$yqe £

ЩЬ. П рисваивав по

С ? 11? 0Cy°Kogoe */W


ПОВТОРЯЕМ уто с иаж fo r ( in t c e l l : lo c a t io n C e lls ) ^ Г]°Э^думеваеМх Промах).
N If0$yt
дои ячейкой массива.
ЕСЛИ догадка пользоаа if (g u e ss = c e ll) (
теля совпала,
r e s u l t = " П о п а л '!; о ,;
T
ИНКРЕМЕНТИРУЕМ ^ л "
n u m O f H it s + + ;
количество попаданий. ' U °^ 0 b ^ . ^ с и^ С э УПи^

b re a k ; ^ ^ 'Uel

, „ K ,_ „ r ^ ?$ ™ **"***«
) // Конец for
/ / ВЫЯСНЯЕМ, была m
это последняя ячейка.
ЕСЛИ количество попа­ if ( n u m O f H it s = l o c a t i o n C e l l s . le n g t h ) {
даний равно 3,
вЫилu ц 3 цикла. но
ВОЗВРАЩАЕМ «Потопил* r e s u l t = "Потопи л " ; Посмотрим. не потопил* ли
а качестве результата. Kdc (тпри попрания), и при
ИНАЧЕ потопления не } // Коней if неодходимос-ща изменим Г
произошло, значит, ВОЗ­ ре^лЬипйтп на «Покорил».
ВРАЩАЕМ «Попал*.
S y s te m . o u t . p r i n t l n (r e s u l t )
ИНАЧЕ пользователь рЫ^орим цолЬзо&тпелк) ре^улЬтлйтп
не попал, значит, («Мимо». если он не §Ьит изменен на
re tu rn r e s u lt ; «Лопал» иЛи «ЛотдопиЛ»).
ВОЗВРАЩАЕМ «Мимо*.
<4
) / / Конец метода $ CufL' 'П
MenioQ.
°17ЧЯ*Ц)ощ)ии мегпоо

134 глава 5
Создание программ

Псевдокод Тестовый
II'., код

Только новое
На этой странице собрана инфор­
мация, с которой вы еще не знако­
мы. Только не волнуйтесь! Ее впол­ /Аетпос) к/Weed
не достаточно, чтобы вы вошли Integer, который
«Зкдетп», как Т1,
в курс дела. Подробности ждут вас у ^ с с , -
Прео5разобЫбатЬ сУ о Ну **щ
в конце этой главы. е^тооек*^0'
бстР строку б Число.

/
Преобразование
S trin g в int. Integer.parselnt("3 ")
W 5 V sw> я в л е н и е
«П овторять у а . казмого эд а м е га й оЧие О
g М есиве Ь & Ш & Ж few jb с л е д а м и
элем ент м еси ва и присвоишь е м «aJicooio^ r"^ 6 ''“ ^ аечсо ' 2“ "»>>Чу
>еМеннои сеДО*-
ц е л о ч и с л е н н о й пере 7 “ ■ * ' * * * int i l l * * * W
V
Ц икл fo r. fo r (in t c e l l : lo c a tio n C e lls ) { }
Я
^ 0g Ц.ОТГ\Ор°г °

е п^e?
ЛдесвЙ. еоеЬо? ^ еЛС' Т ^ ^
о Jyjtfve- \ ентл'
й . ЭЛе*е*
пРо ^ 0 9 ^ и е Л в Э ^ е Л е ^
1! е ж . Д .
•Элемент AWccugd. Пока Э л е м е н у ф ^ ^ ^

в се$$ n
гЛл€ьи

Оператор ++^о5аблЯет единицу


К зндЧекик» переменной (то естг,Ь
Постинкрементный Это инкремент)-
оператор.
n u mOfHits++
выражение numOfHits++ — тпо Же
самое (б данном случае), Чгпо
ПикпОfHits = numOfnits + X. ко §олее
Эффективно.

Оператор break.
break;
Мгновенно выбрасывает бас из цикла. Прямо з^есЬ.
Никаких итераций, условий — сралч на выход!

вы здесь ► 135
Создание настоящ ей игры
П севдокод
О кончательны й в а р и а н т кос)з с)ля Simple'PotCom
Э т о не . и Sim pU'PotCom Tester
глупые вопросы public class S i m p le D o t C o m T e s t D r iv e {

Что случится с методом public static void m a in (String[] args) (


Integer.parselntO, если передать ему SimpleDotCom dot = new SimpleDotCom{);
не число? Распознает ли он цифру, за­
int[] locations = (2,3,4);
писанную словом, например «три»?
dot.setLocationCells(locations);
String userGuess = "2";
• Integer.parselntO работает толь­
ко со строками, которые представ­ String result = dot.checkYourself(userGuess);
ляют собой ASCII-значения для цифр }
(0 ,1,2, 3,4, 5, 6, 7, 8, 9). Если вы попы­
таетесь разобрать строки вроде «два» )
или «слоник», возникнет ошибка
(то есть будет запущено исключение,
но мы не будем затрагивать эту тему,
пока не дойдем до соответствующей public class S im p le D o t C o m {
главы;пока же словосочетания «воз­
никнет ошибка» будет достаточно). int[] locationCells;
int numOfHits - 0;

% В самом начале книги при­ public void s e t L o c a t i o n C e l l s (int[] Iocs) {


водился пример цикла for, который locationCells = Iocs;
заметно отличался от представлен­
}
ного здесь. Это два разных стиля
для циклов for? public String checkYourself(String stringGuess) {
int guess = Integer.parselnt(stringGuess);
String result = "Мимо”;
О • Да! Начиная с первой версии, for (int cell ; locationCells) {
в Java поддерживался единственный if (guess == cell) {
вариант цикла for (мы рассмотрим его result = "Попал";
позже в этой главе), который выглядел numOfHits++; Что мы должны уви­
так: break; деть при запуске этого
for(int i = 0; i < 10;i++){ } кода?
) .• / 3 f c .'..o . fee-: iir t r .i
// Выполняем что-нибудь 10 раз Тестовый код создает
} if (numOfHits == объект SimpleDotCom
locationCells.length) ( и передает ему местопо­
Вы можете применять этот формат для ложение под номерами
result = "Потопил";
любых нужных циклов. Но с версии 2, 3, 4. Затем он шлет вы­
Java 5.0 (Tiger) вы также можете поль­ }
System.out.println(result); мышленный пользова­
зоваться улучшенным циклом for (это тельский код 2 в метод
return result;
официальное описание), когда нужно checkYourSelfO- Если код
перебирать элементы массива (или работает правильно,
другого вида коллекции, как будет по­ то мы должны увидеть
казано в следующей главе). Для этих следующий результат;
целей сгодится и старый цикл for, но
- . . .. .-V . <". - ,.
его улучшенная версия предоставляет Здесь есть небольшая ошибка. Программа ЗО’ла S in p ie D o tC o m T e stO riy c
больше возможностей. компилируется и запускается, но иногда... honaji '• - .- <■
Сейчас не будем об этом думать, но придется : c"’ v.: •
разобраться с проблемой чуть позже.
136 глава 5
Создание программ

Н аточите свой кзрзиЗаш

Мы создали тестовый класс и класс SimpleDotConn. Но у нас все еще нет


самой игры. Пользуясь кодом с предыдущей страницы и техническим за­
данием для игры, напишите свой вариант псевдокода для игрового клас­
са. Мы добавили несколько готовых строк, чтобы вам было с чего начать.
Полная версия псевдокода игры находится на следующей странице,
поэтому не подглядывайте, пока не закончите это упражнение1 . Класс SimpleDotComGame
делает следующее.
1 Создает объект
МЕТОД public static void main (String [] args)
SimpleDotCom.
ОБЪ ЯВЛЯЕМ переменную numOfGuesses типа int для хранения количества
ходов пользователя. 2. Придумывает для него место­
положение (три последо­
вательные ячейки в одном
ряду).
3. Предлагает пользователю
сделать ход.
4. Проверяет введенные дан­
ные.
5. Повторяет, пока «сайт» не
ВЫЧИСЛЯЕМ случайное число от О до 4 для местоположения
начальной ячейки. будет потоплен.
6. Сообщает пользователю,
сколько ходов он сделал.

ПОКА «сайт» не потоплен:


П олны й игро&ой ди алог
ПОЛУЧАЕМ пользовательский ввод из командной строки.
File Edit Window Help Runawa'

%j a v a S im p le D o tC o m G a m e
В в:е д и т е ч и с лоо--- 2•
Попал
Введите число 3
Попал

вы здесь » 137
Создание настоящей игры

ТТсе&докод Эля класса Si'mplePotCom^rame


"рее э т о находится в н утр и m ainO
Е с т ь некоторые вещи, которые нужно принять на веру. Например, одна из
строк псевдокода гласит: «ПОЛУЧАЕМ пользовательский ввод из команд­
ной строки». На текущий момент это немного больше, чем нам нужно реа­
лизовать. К счастью, мы используем ООП, то есть можно попросить другой
класс/объект о выполнении определенного действия и не задумываться, как
именно он это сделает. При написании псевдокода вы должны понимать, что
когда-нибудь у вас будет возможность сделать что угодно, а сейчас нужно
направить все умственные усилия на продумывание логики.

public static void main (String [] args)


ОБЪ ЯВЛЯЕМ переменную numOfGuesses типа int для хранения количества ходов пользователя.

СОЗДАЕМ новый экземпляр класса SimpleDotCom.

ВЫ ЧИСЛЯЕМ случайное число от 0 до 4 для местоположения начальной ячейки.

СОЗДАЕМ целочисленный массив с тремя элементами, используя сгенерированное случайным


образом число и увеличивая его на 1, а затем на 2 (например, 3, 4, 5).
ВЫ ЗЫ ВАЕМ метод setLocationCells() из экземпляра SimpleDotCom.

О БЪ ЯВЛЯЕМ булеву переменную isAlive для хранения состояния игры. ПРИСВАИВАЕМ ей значение true.

ПОКА «сайт» не потоплен (isActive == true):

ПОЛУЧАЕМ пользовательский ввод из командной строки.

//П Р О В ЕР Я ЕМ полученную информацию.


ВЫ ЗЫ ВА ЕМ метод checkYourSelff) из экземпляра SimpleDotCom.

ИНКРЕМЕНТИРУЕМ переменную numOfGuesses.

//П РО В ЕРЯ ЕМ , не потоплен ли «сайт».


ЕСЛИ результат равен Потопил.

ПРИСВАИВАЕМ переменной isAlive значение false (это значит, что мы не хотим снова заходить в цикл).

ВЫВОДИМ количество попыток.

КОНЕЦ ВЕТВЛЕНИЯ
О б в е ш и с о $ е ш >
КОНЕЦ ЦИКЛА
Не загружайте одну половину мозга на протяжении
КОНЕЦ МЕТОДА длительного времени. Использовать только левую часть
более 30 минут — то же самое, что полчаса работать
одной левой рукой. Устраивайте каждой половине мозга
перерыв, меняя их через равные промежутки време­
ни. Загрузив одну сторону, вы даете другой отдохнуть
и восстановиться. Левая часть мозга отвечает за такие
вещи, как последовательности, решение логических
задач и анализ; правая же сторона больше нацелена
на метафоры, креативный подход, распознавание
138 глава 5 и визуализацию. ________________
Создание программ

------КЛЮЧЕВЫЕ М О М Е Н ТЫ ^® -----------------
■ Начинать работу над J a v a -программой ■ Выбирайте цикл fo r вместо while, если
нужно с высокоуровневого проектирова­ точно знаете, сколько итераций необхо­
ния. димо выполнить.

■ Используйте оператор пре-/постинкре­


■ Как правило, в процессе создания ново­
мента для добавления к переменной
го класса следует написать три вещи:
единицы (х++;).
псевдокод; ■ Применяйте оператор пре-/постдекре­
мента для вычитания из переменной
тестовый код; единицы (х--;).

реальный код (на языке Java). • Используйте метод In te g e r .


p a r s e l n t ( ) для получения целого чи­
■ Псевдокод должен описывать, что д е ­ сла из строки.
лать, а не как это делать. Реализация ■ I n t e g e r . p ar s e l n t ( ) работает
начинается позже. только тогда, когда цифры представлены
в строковом значении («О», «1», «2» и т. д.).
■ Используйте псевдокод для упрощения
разработки тестового кода. ■ Используйте оператор break для преж­
девременного завершения цикла (даже
■ Пишите тестовый код перед реализацией если проверка условия все еще возвра­
методов. щает true).

с Сколько роз L
к тебе заходили
в прошлом Вернувшиеся
. месяце? . по сетители
считаю тся?

2» - »

J 1 р'УС&ЯЛСх ЯДф I T С\Ч-К-ОгО 'IQ foO j

вы здесь ► 139
Создание настоящей игры
Псевдокод Тестовый
код
М етод т а т О &игре
Как и в случае с классом SimpIeDotCom, подумайте о фрагментах кода, которые
вам хочется (или нужно) улучшить. Отметки ^ предназначены для элементов,
на которые нам хотелось бы обратить ваше внимание. Они рассматриваются на
следующей странице. Мы пропустили создание тестового класса для игры, потому
что он просто здесь не нужен. Класс SimplcDotComGame состоит лишь из одного
метода, поэтому нет смысла писать для него проверочный код. Делать отдельный
класс, который будет вызывать метод m ain() из этого класса? Нет необходимости.
сл езть
ОБЪЯВЛЯЕМ перемен­ pub l i c static v o i d m a iin
n (String!] args) {
^KC-nuMec^o/AKO^-
ную nurn0fGiies?85. типа
int для хранения количе­ int nuraOfGuesses = 0 ;
ства ходов пользовате­ класс, к с щ о р С ч й
З'то с п е ц и а д Ь н Ь ш
ля: присваиваем ей О. G ameHelper h e l p e r = ne w G a m e H e l p e r (); содержит?) Mew}oq ^ля приема
СОЗДАЕМ новый п о ; ю з о ё а'1пелЬского Пока
экземпляр класс
cqenaeM Suq, Чтгр 3тг)0 ЧасщЬ Java.
SlmpieDotCom.
SimpIe D o t C o m theDo t C o m = new S i m p I e D o t C o m (); CojjqdeM о Э Ъ е ю П ^ сай г и 3 .
ВЫЧИСЛЯЕМ случай
ное число от О до 4 для ® Генерируем случайное
местоположения началь­ int randomNum = (int) (Math, random() * 5) ; {— - ...... _ л .
число ^ля первой ячейки
ной ячейки.
и иоПолЬ^уем его а ж
СОЗДАЕМ целочислен­
ный массив с местопо ю )£ формирования массива ячеек.
жеиием грех ячеек и int[] l ocations = (randomNum, r a n d o m N u m + 1 , r a n d o m N u m + 2 };

ВЫ ЗЫ ВАЕМ метод theDotCom.setLocationCells(locations); * с г й щ у ® М в С У П ® 1. ‘


setLocatlopCellsO из
Ж-вние его ЛЧееК (м^ссиЮ.
экземпляра.
bool e a n isA l i v e - true, Co^qaeM 5уле£у переменную. ’+Л)о5Ы
ОБЪЯВЛЯЕМ булеву
переменную isAHve. Про^ерЯкдЬ £ цикле, ice закончилась
ПОКА «сайт» не потоп ' т иг?еХ" ТюЯЧ4'1^ с'гп?сЖ'*’
while( i s A l i v e = true) {

ПОЛУЧАЕМ пользова­
String gue s s = h e l p e r .g e t U s e r I n p u t ("Введите число");
тельский ввод.
/ / ПРОВЕРЯЕМ его. String r e s u l t = theDotCom.checkYourself(guess) V cum «сайтп» npo.
ВЫ ЗЫ ВАЕМ метод ✓___ */1ндремекуг>ирчем
checf»YourSelf() из num O f G u e s s e s - K ; - ‘ 0 •J Полученное
Количество Попыток. S^HHble; cox
SiM.pteDotCom. 'роняем,
if ( r e s u l t . e q u a l s ("Потопил")) {
ИНКРЕМЕНТИРУ­
ЕМ переменную З У Л умщ ? п е р е м к­
numOfGuesses. isAlive = false;
н у » Чипа String.
ЕСЛИ результат равен
S y s t e m . o u t . p r i n t l n ("ВамЧлотре<5овалось"\+ n u m O f G u e s s e s + "попыт о к ( и ) ");
«Потопил*.
ПРИСВАИВАЕМ пере ) // Згверсаэм if TlcnrioqjjeH л и « с а й т » ? Г . _ ^
менной isAHve значение ls« v e зкипение f u h e l ^ ™
false. ) / / Заверзаом w h ile
ВЫВОДИМ количестве
попыток. количествопопьщок. 5
) ■/ З э а з р г а е н м&тад m ain

140 глава 5
Создание программ

П севдокод

randomOugdOwrfnputO
Эта страница посвящена методам тле которого Последующий Элемент
Прощает, Чисдо спщ 0 3 °
randomO и getU serInput(). Здесь меняет», с&и -УПОП на законный А вкЛК«щелЬНо\
г, ,
(не
приведен лишь краткий обзор, ско кох. AU-tb-ranc/o-n, ^о^рдоцде-уп Чщо Э-щл формам C W -
позволяющий получить общее double, поэтому нео&ооимо При&-
СТЦи его
вяо к
V itvf ____ Г ЧдЯ r,pu^e9eW1Ae тг»иПО^
представление об их работе. сущ irrf
(ном куж^х послеоо-
{ l i ^ ч

go^CxXUJ^etn Чисдо ото О


О классе GameHelper вы подробнее бопелЬноопЬ целЫх Чисел м е ^
прочтете в конце этой главы ^о 4 (тяуо ес-кпЬ о " 4 -9 9 9 .
О и 4). 3 процессе отцсекаетцсЯ присвоенное к
5роандя ЧдстпЬ <fcuUe.
Генерируем случайное /
© число. / i* 5)
int randomNum = (int) (Math.random()
T
A\bt о5ья&ЛЯем переменную /
Класс, C c t t iроеннЫй
T ^ класса
>T,uriHUvty\5L хранения случай- g Jovu
ного Числа.

^ Сч р 0-

Л г^ - - 4

а Г » - ,ь » ь в ы
Ранее созданный нами
Экземпляр вспомогатель­
Получаем поль­ ного класса. Он называемся ^ Р ^ Л а 3 о ^ го
© зовательский ввод GameHeJPper. и вы Пока с HUM
с помощью класса не знакомЫ (но euJ,e позна­ ^ ^ е д ь с к и а & оа
GameHelper. комитесь).
«Г /
String guess =
t
А^Ы. о$Ъяёили сороковую
т
helper.getUserInput("Введите число")

А\екnog класса 6атг\еНе-?рег. Предлагающий


Пользователю Неописанные. Он Читает
Переменную 4ЛЯ хранения
ПодЬ,зоЙпт,едЬского Ш оу\, их после того, как пользователь кохсол
Который подучаем oSpamno кнопку Inter, и возвращает результат
в биде строки.

вы здесь > 141


Готовый класс G am eH elper

Последний класс: GameHelper


Мы создали классы Sim pleD otC om и Sim pleD otC om G am e. Просто скопируйте* код, приве­
денный ниже, и скомпилируйте
Остался вспом огат ельны й класс, который содержит метод
его в класс GameHelper. Поместите
getU serInput(). Код для получения пользовательского ввода
все три класса (Sim pleDotCom ,
включает в себя элементы, которые мы пока не рассматрива­
SimpIeDotComGame, GameHelper)
ли. Сейчас вам многое будет непонятно, поэтому оставим его
в один каталог, который будет
на потом (до главы 14).
рабочим.
Каждый раз, когда вы видите
Кео, ЛоиовиЛ ..
■ ,nompf6*mu», знайте, что на­
ходящийся рядом с ним код нужно
Я тут при­
просто принять на веру и точно
б е р е гл а н е м н о го перепечатать. О том, как этот код
к о д а , т а к ч то те б е работает, вы узнаете позже.
не п р и д е тся го то ­
ви ть е го са м о м у .

Код, готовый
к употреблению
im p o r t : j a v a . i o . * ;

p u b lic c la s s G a m e H e lp e r {

p u b lic S t r in g g e t U s e r ln p u t ( S t r in g p ro m p t) {

S t r in g in p u t b in e = n u ll;

S y s t e m .o u t . p r in t ( p r o m p t + " " );

try {

B u ffe re d R e a d e r is = new B u f f e r e d R e a d e r (

new I n p u t S t r e a m R e a d e r ( S y s t e m . i n ) ) ;

in p u t L in e = i s .read Lin e();

if ( i n p u t L i n e . l e n g t h () = 0 ) re tu rn n u ll

} ca tch ( IO E x c e p t io n e) {

S y s t e m .o u t . p r i n t l n ( " IO E x c e p t io n : " + e );

i
re tu rn in p u t L in e ;

}
)
‘ Мы не сомневаемся, что вы обожаете набирать
текст, но если у вас будут более важные дела, можете
заглянуть на сайт wickedlysmart.com и скопировать код.
который мы уже приготовили.
142 глава 5
Создание программ

Сыграем Что такое? Ошибка?


Вот что пр оизойдет, е сл и м ы Только не э т о !
за п усти м игру и введем чи­ В от что будет, если мы вве­
сла 1, 2 , 3, 4 , 5, 6. В ы гл я д и т дем 1, 1, 1.
н е п л о хо .

Полный игровой диалог Другой пример игрового диалога


Количество попыток может изменяться Не может быть!

| F«e Edit Window Help Smile 1 I File Edil WindowHei^Tami |

% java SimpleDotComGame %java SiropleDotCoraGajne


• ■ :■ ■■ ■ ■ ‘. ’
В вед и те ч и с л о 1 . : Введите число 1
Мимо Попал
В вед и те чи сл о 2 Введите число 1
Мимо Попал
В веди те ч и сл о 3
• . Введите число 1
Мимо . -у ^ '• . У Потопил
В веди те ч и сл о . 4 Вам потребовалось 3
попыток(и)
Попал
У ' . У ' у '
В веди те число 5
д * Н зточите свой
Попал ‘ j '■<? »
карандаш-
В в ед и те ч и сл о 6
Потопил
Вам п о т р е б о в а л о с ь б
Во т так интрига!
п оп ы ток(и ) Найдем ли мы ошибку?
Исправим ли мы ее?

Потерпите До следующей главы, и вы получите


ответы на эТй вопросы и не только...
А пока попробуйте разобраться, что пошло
не так и как это исправить.

вы здесь ► 143
Циклы for

Поговорим о циклахjor
В этой главе мы смогли описать весь код игры (но в следующей главе
мы вернемся к нему, чтобы закончить полную версию). Ранее мы не
хотели отвлекать вас подробностями и справочной информацией,
поэтому все это собрано здесь. Начнем с особенностей циклов for.
Но, если вы программировали на C++, можете смело пропускать
следующие несколько страниц.

Обычные (неулучшенные) циклы foi


^ !СЬНаХ°Э“ П сЯ « о ,
О п е р т°р
^ Л о Ц ц^) ^ 'Р ^ Ь с Я

fo r (in t i = 0 ; i < 100; i+ + ){ V , “Повторяйте 100 раз


/ Г
И^ЦисГЛцзлицЯ. Условие- еи^У*0**° е

На русском языке это будет звучать так: «П овтор ять 100 раз».

Как это в ы гл я д и т с точки зрения компилятора:


* создать переменную / и присвоить ей 0;
* повторять, пока /' меньше 100;

* в конце каждой итерации прибавлять к i единицу.

Часть первая: и н и ц и а л и за ц и я .
Используйте эту часть для объявления и инициализации переменной,
которая задействована внутри тела цикла. Чаще всего она выступает в роли
счетчика. На самом деле здесь можно инициализировать сразу несколько
переменных, но об этом мы поговорим позже.
Часть вторая: у с л о в и е .
Это место, где проверяется условие. Что бы здесь ни находилось, оно
должно возвращать булево значение (true или false). Вы можете предусмо­
треть условие вроде (х >= 4) или даже вызвать метод, который возвращает
значение типа boolean.
Часть третья: и т ер а ц и о н н о е в ы р а ж е н и е .
Сюда нужно поместить одно или несколько выражений, которые вы хотите
выполнять при каждом проходе цикла. Помните, что они выполняются
в конце каждой итерации.

144 глава 5
Создание программ

Путешествия сквозь цикл 5


fo r ( i n t i = 0; i < 8; i+ + ) {
S y s t e m .o u t .p r in t in ( i) ;
}
System , o u t . p r i n t In (''Го т о в о ") ;

++ ----
Оператор Пре- и Пост- Инкремента/Декремента

Сокращение для добавления или вычитания еди­


ницы к/из переменной
Х++ ;
то же самое, что:
X = X + 1 ;
Оба выражения означают одно и то же в таком контек­
сте: «Добавить 1 к текущему значению х» или «Инкре­
ментировать х на 1».
Разница м еж ЗДог и while
И:
Цикл whileсодержит только условие и не х — ;
предусматривает встроенной инициализации
то же самое, что:
или итерационного выражения. Он хорош в тех
случаях, когда неизвестно, сколько раз нужно х = х - 1;
повторить тело цикла, и следует продолжать, Но, как всегда, этим все не ограничивается. Располо­
пока истинно какое-то выражение. Но если жение оператора (перед или после переменной) может
вы знаете, сколько раз необходимо пройти повлиять на результат. Добавляя оператор перед
через цикл (например, известна длина масси­ переменной (например, ++х), мы говорим:«Сначала
ва, нужно выполнить действие 7 раз и т. д.)#for инкрементируем х на 1, а потом используем это новое
подходит больше. Рассмотрим предыдущий значение». Это важно только в тех случаях, когда
цикл, переписанный с использованием опера­ ++х применяется не отдельно, а внутри более объем­
тора while: ного выражения.
i n t i = 0 ; < ------- int х = О; int z = ++х;
В итоге: х равно 1, z равно 1.
w h i le ( i < 8) {
Но разместив ++ послех, вы получите другой резуль­
S y s t e m .o u t .p r in t ln ( i) ; тат:
i+ + ; i n t х = 0; int z = х + + ;

> В итоге: х равно 1, но z равно 0! Переменная z принима­


ет значение х до того, как та увеличилась на единицу.
S y s t e m .o u t .p r in t ln (" Г о то в о " );
вы здесь ■* 145
Улучшенный for

Улучшенный цикл for


Начиная с версии 5.0 (Tiger), язык Java приобрел еще один вариант цикла f o r ,
который называют улучшенным. Он создавался для упрощенного перебора эле­
ментов в массиве или другом виде коллекций (о других коллекциях вы узнаете
в следующей главе). Улучшенный цикл f o r вскоре стал частью языка, так как
по сути делал то же самое, что и обычный f o r , только эффективнее. Мы снова
вернемся к нему в следующей главе, когда речь пойдет о коллекциях, отличных
от массивов.

ОбЪяёлЯеМ переменную <)ЛЯ


итераций, ко^орсхЯ дузетп (■) н
хрдкитф один.ЭЛеМенлщ w * V „ l 9uyr,c*

Массива. Супе^ 4 ш < ^ ен ия

/ ■
for (String паше nameArray^ { }
У *
ЭлемекгпЬч. массив
Зояж нЬ. 5(аупЬ nepeMe Рди&хфсЯ yipeacrn^b-me. 4>г\ $ « W j» }:
соьместгцимы с
ооЪЯЪЛенной
о.
m s lit! ! L
Переменной.
^ндЧение « т р - j • | I

На русском языке это будет звучать так: «Для каждого элемента в массиве Примечание-.
nam eArray: присвоить элемент переменной name и запустить тело цикла». нек<лтор1ле г '
g злбисимсс>т\и
сщ используемого
Как это вы гл яд и т с точки зрения компилятора. ранее
Программирования
* Создать строковую переменную с именем пате; присвоить ей значение null. отпносЯтпсЯ
к ^л^МсиенноМ^
* Присвоить переменой name значение первого элемента из массива nameArray.
цик/у f оГ
* Запустить тело цикла (блок кода, заключенный в фигурные скобки). к иуиклам * v *
йЬ» или «for
* Присвоить переменной name значение следующего элемента из массива nameArray. ^сщоМу Ч^о
* Повторять, пока в массиве остаются элементы. 4uwl>crrr\ Эчпо
именно чгуАК: *1оГ
Часть первая: объявление переменной для итераций. еаЖ 'п в
coWect'on—*
Используйте эту часть для объявления и инициализации переменной, чтобы работать каждого Элемент
с ней в теле цикла. С каждой итерацией цикла переменная будет хранить следующий эле­ g коллекции..»)-
мент коллекции. Ее тип должен быть совместим с элементами массива! К примеру, вы не
можете объявить итерационную переменную типа int для перебора массива типа StringO.

Часть вторая: текущая коллекция.


Это должна быть ссылка на массив или другую коллекцию. Не волнуйтесь о других видах
коллекций, отличных от массивов, — вы познакомитесь с ними в следующей главе.

146 глава 5
Создание программ

П р е о б р а з о в а н и е S trin g в in t "Приведение
int guess = Integer.parselnt(etringGuttss); простых
Пользователь вводит номер ячейки в ко­
мандной строке, когда программа пред­
типов
лагает ему это сделать. Номер приходит
в виде строки («2», «О» и т. д.), которую
игра передает в метод checkYourSelf().
Но адреса ячеек представлены в виде
целых чисел в массиве, и вы не можете
сравнивать int со String. может быть приведен к
long s h o rt
Например, это не будет работать:
String num = «2»;
int х - 2; Н о при этом
if (x == num) // Ужасный взрыв!
можно к о е -ч то
потерять.
Увидев такой код, компилятор просто
посмеется над вами: В главе 3 мы говорили о размерах различных примитивов и о том,
что нельзя поместить большую вещь в маленькую:
o p e r a t o r ==■ c a n n o t be a p p l i e d
to i n t ,g a v a .l a n g .S t r i n g long у = 42;
int х = у; //Не скомпилируете»
if (x = = num) { }
A
Тип long больше int, и компилятор не может знать, где этот тип
был раньше. Может, он выпивал вместе с другими переменны­
ми типа long и «принял» по-настоящему большую дозу. Чтобы
Чтобы не попасть впросак, мы долж­ заставить компилятор сжать переменную до размеров менее
ны превратить строку «2» в число 2. вместительного типа, можно задействовать оператор приведения.
В библиотеке классов Java предусмотрен Он выглядит так:
класс Integer (именно класс Integer, а не long у = 42; // Пока все хорошо
простой тип int), и одна из его функ­
int х = (int) у; // х = 42 Отлично/
ций — принимать строки, представ­
ляющие числа, и преобразовывать их Появившееся здесь приведение типов говорит компилятору взять
в настоящие числа. значение переменной у, обрезать его до размеров int и присвоить
переменной х оставшееся. Если значение у оказалось больше,
чем максимальное значение х, то мы получим странное (но допу­
стимое*) число:
vjyxcc. 6 c ^ ° e'r0^:?Ui TJpuKUAvieTr] long у = 40002;
£ строку // 40002 превышает лимит для типа short в 16 бит
short х = (short) у; // х теперь равен -25534!
i 1 Суть в том, что компилятор позволяет это сделать. Допустим,
Integer.parselnt("3 ") у вас есть число с плавающей точкой и вы просто хотите получить
его целую часть (/л/):

Летпод
/
класса Integer.
float f = 3.14f;
int x = (int) f; // x теперь равен -25534!
спосоанЫй npeoSpd^c&t&r^b Даже не думайте о том, чтобы приводить переменные к типу
стцрок'у g Число, которое она boolean или наоборот.
ПредстпаёлЯеуп. ' * Здесь появляются знаковые разряды, «дополнительный код»
и другая компьютерная ерунда, речь о которой пойдете Прило­
жении Б.
вы здесь ► 147
Упражнение: поработайте виртуальной машиной

Поработайте Мр^уальноц, машиной.


JaVa-^айл на этьой. стиран и>ц,е —
э1Ьо Полноценный? и?сХо^ни?К. Ф а ч и
задача — п ри ^ орц ^ ьс^ JVM
и? опрс$ели??ьь, чть.о программа
fibiftetferh, на экран, если?
ее зап/с-Нъа-НьЬ.

class Output (

public static void main(String [] args) {


Output о = new Output();
о . go ( ) ; -И Л И -

void go() {
int у = 7;
for(int x = 1; x < 8; x++) {
y++;

if (x > 4) {
System.o u t .print(++y + " "); -И Л И -

}
if (У > 14) {
System.out.println(" x = " + x);
break;

}
)
}
}

148 глава 5
Упражнение: магнитики с кодом

Магнитики с кодом
Части рабочего Java-приложения разбросаны по всему холодильни­
ку. Можете ли вы восстановить из фрагментов кода работоспособ­
ную программу, которая выведет на экран текст, приведенный ниже?
Некоторые фигурные скобки упали на пол. Они настолько малы,
что их нельзя поднять. Можете добавлять столько скобок, сколько
понадобится!

вы здесь > 149


JavoCross

J aVaCms
Каким образом кроссворд
поможет вам в изучении
Java? В нем все слова связа­
ны с этим языком. К тому же
подсказки содержат мета­
форы, игру слов и т. п. Такая
интеллектуальная зарядка
открывает новые подходы
к освоению Java.

Ф к ‘^?г-'- ': г“. i

По горизонтали По вертикали
1. Инкремент, который 8 .32-битный. 15. Помогает уйти раньше 22. Предварительный код.
следует после. времени.
9. Выглядит как простой 23. Цикл.
2. Инкремент — это один тип, но... 16. Пристанище
24. Уменьшает на единицу.
из его видов. числа пи.
10. Рабочая лошадка
25. Не участвует в приве­
3. Цикл, состоящий из у класса. 17. Вид инкремента.
дении типов.
нескольких частей.
11 Невсамделишный. 18. То же самое, что ++.
4. Изменение.
12. Whilennnfor. 19. Большой набор инстру­
5. Ответ метода. ментов.
13. Скомпилируй это
6. Причудливое компью­ и ______ . 20. Установить первое
терное слово для созда­ значение.
14. Может быть локальной,
ния чего-либо.
а может принадлежать 21. Обновляет значение
7. Метод из класса Math. классу. поля.

150 глава 5
Смешанные сообщ ения

Ниже представлен код небольшой программы на языке


Java. Но один ее блок пропал. Ваша задача — найти блоки
(слева), которые выведут соответствующий программный
результат, если их вставить в код. Не все строки с выводом
будут использованы, а некоторые из них могут применять­
См еш анны е
ся несколько раз. Соедините линиями блоки кода и подхо­
дящий для них результат.

c l a s s M ix F o r 5 {
p u b lic s t a t i c v o id m a i n ( S t r i n g [] a r g s ) {
in t x = 0;
in t у = 30;
fo r ( i n t o u te r = 0 ; o u te r < 3 ; outer+ + ) {
f o r ( i n t in n e r = 4 ; in n e r > 1 ; i n n e r — ) {

у = у - 2;
if

}
( x == 6 )
b reak;
{
'f e a s t s ?
x = x + 3;
}
у = у - 2;
}
S y s te m .o u t.p r in t ln ( x + " " + у) ;

Возможные блоки: Возможный результат:

X => X + 3 ; 45 6
Coeqw*u™ e
х = х + 6; 36 б
с U3
х — х + 2; 54 6
Ъ о ую м *** п
60 ю

18 6

6 14

12 14

вы здесь ► 151
Ответы

П о ^ о м й И ъ е М ^ / а л ь н о й м а ш и o il Магнитики с кодом
class Output { class MultiFor {

public static void main[String [] args) { public static void main(String [] args) {
Output о = new Output(>;
for (int x = 0; x < 4; x+ +) (
o.go ();

}
for(int у = 4; у > 2; у— ) {
void go() { System.out.println(x + " " + y);
int у = 7; }
for(int x = 1; x < 8; x++) (
if (x == 1) { Что бы случилось,
У++; если бы этот блок
x+ +;
if (x > 4) ( кода шел перед
) вторым циклом for?
System.out.print(++y + " ");
}
} >
if (У > 14) { )

System.out.printlnC x = " + x) ;
break;

}
}
)

i Вы не забыли про оператор


break? Как он влияет на
результат работы программы?

152 глава 5
Ответы

JaVaCrw

бялеианныа
сообщ&\т$
Возможные блоки: Возможный результат:

12 14
вы здесь > 153
6 Знакомьтесь c Java АР!

Использование библиотеки Java

Вместе с Java поставляются сотни готовых классов. Можете не тратить


время на изобретение собственного велосипеда, если знаете, как отыскать нужное
в библиотеке Java, называемой еще Java API. Думаем, что у вас найдутся более важные
дела. При написании кода сосредоточьтесь на той части, которая уникальна для
вашего приложения. Наверняка вы знаете программистов, которые приходят на работу
не раньше 10 часов утра и уходят ровно в 5 часов вечера. Они используют Java API.
На следующих страницах вы займетесь тем же. Стандартная библиотека Java представляет
собой гигантский набор классов, готовых к применению в качестве «строительных
блоков». Они позволят вам создавать приложения преимущественно из готового кода.
Заранее подготовленный код, который мы приводим в книге, не нужно писать с нуля, хотя
набрать его все же придется. Java API содержит большое количество кода, который даже
набирать не нужно. Все, что от вас требуется, — научиться его использовать.

это новая глава » 155


У нас все еще есть ошибка

$ предыЭушей главе мы оставили небольшую


интригу, а именно ошибку

Как зто должно выглядеть Где закралась ошибка


П о см о тр и те , что п р оизойдет, Вот что сл у ч и тс я , е с л и м ы
е сл и м ы зап усти м програм му введем 2 , 2 , 2.
и введем числа 1, 2 , 3 , 4 , 5 , 6.
В ы гл я д и т нормально.

Полная версия игрового диалога Другой итровой диалог


Количество попыток может изменяться Не может быть!

! File Edit Window Help Faint -------------------- 1

%java SimpleDotCotnGame
Введите число 2. г
• I

Попал
Введите число
Попал •
Введите число
Потопил ■
Вам потребовалось 3 j
попыток(и) . . ;

'Ь текущ ей версии при


попадании вы м ож ете п р о с то
п о в то р и ть два раза удачный
ход и п о то п и ть « с а й т » !

156 глава 6
Знакомьтесь с Java API

Ч то же случилось?

public String checkYourself(String stringGuess) {

int guess = Inteaer.parselnt (stringGuess) String


' _ fe ini* J

String result = " Мимо”; L° ^ eM ^ р ^ н н у х ^ л х хранения

for (int cell : locationCells) {

Здесь кроется if (guess = cell) {


ошибка.
Мы засчитываем 4 вбниёдемход
result = ’’Попал"
попадание каж­ ЪолЬзо&щелЯ
r %bt ПQt)dJPif ?1пил\ Эле/Аек-щом
дый раз, когда n u m O f H it s +Ч*; A~
пользователь
\
(ячейкой) Mdccu&t
угадывает адрес break; U0 цикл*, «eyn
ячейки, даже неоодсс
если она уже } >■ .--Соней j. ypy<zuа Ячейки. 1
была поражена!
} ;// Конец f o r
BbixoyuM u j Ujukjvx
Нужно научиться
if (numOfHits = locationCells.length) — Но Про^еряел\
узнавать, попа­
«Потоплены» ли Mb.
дал ли пользо­ result = "П о т о п и л "; firipu notlcfcjcwusO.
ватель в кон­
u и<3^еняе/А ре^улз-та-уп
кретную ячейку. } .// КоаН&ц if на *lloiTjonu/]».
При повторном
попадании в эту System.out.println (result) ; *--- ]&i£ oqu M no^bjofcnmeJlio резуЬтщлщ
же ячейку не («Мимо3»,если он. ке Sbui измекек
надо засчиты­ return result; Hd «Погк^Л3*или ^ПотпопиЛ^).
вать ход. ^ Зо^раЦаел\ редультадтп
} .7 F-он^ц невода *И я& я& ю Щ ий меуцод.

вы здесь ► 157
Исправление ошибки

Как мы э т о испра&им?
Нужно найти способ узнавать, по пал л и игрок в конкретную ячейку. Р ассм о т­
рим возможные варианты , но перед эти м сф о р м ули р уем , что уже известно.

У нас есть виртуальны й ряд, со стоящ ий из сем и ячеек, три из ко то р ы х будет


занимать объект DotCom. В это м виртуальном ряду показан « с а й т» , состоящ ий
из ячеек 4 , 5 и 6.

0 1 2 3 4 5 6

О бъект DotCom содерж ит перем енную экзем пляр а — ц ело чи слен н ы й


м а сси в , хранящ ий адреса зан и м аем ы х ячеек.

П(

locationCells
(переменная экзем пляра
объекта DotCom).
Чиы^ «“ "loptM ^ Л 5“ б-* Ю

(t) в а р и а н т первый
Можно создать второй м ассив и при каждом попадании д е л а ть в нем
со о тветствую щ ую зап и сь, а затем проверять, стр е л я л и л и в э ту ячей­
ку раньше.

Значение true в ячейке г

Г ео&п = ’поп “ 9 е* "


и н д е к со м н п Q С 3>Т)и/Л Ж е
V уже с-треяяльи^Уг0М * * ССи^е nCeftfe),

Массив hitCalls
(э то новая пере­
» Например, если Ячейка
менная экзем пляра с и н д ексом 2 nnn^L-
в к л а ссе DotCom,
хранящ ая булев
м асси в). р ^ и^е>Г1ся значение true.

158 глава 6
Знакомьтесь с Java API

flep&biu вариант слишком усложнен


В первом варианте вы п о лн яется больш е д е й с тв и й , чем можно ожи­
д а ть. П р и каждом попадании необходим о изм енять со стояние второго
м асси ва (h itC e lls ), но перед эти м нужно проверить его и вы ясни ть,
не стр е л я л и л и в э ту ячейку раньше. Конечно, это будет работать,
но долж но сущ ествовать более изящ ное решение.

( 2) в а р и а н т В т о р о й
Можно ограничиться о р игинальн ы м м асси во м , изм еняя значение пора­
женной ячейки на -1. П р и таком п о д хо д е м ы будем и спользовать д л я
проверки и изм енений один м ассив.

locationCells
(переменная экзем пляра
объекта DotCom)

в тор ой В>зризнт немного


лучше) но &се еше сложно&зт
Второй вариант не такой сло ж н ы й , как первы й, но тоже не о тл и ч а ется особой
эф ф екти в н о сть ю . Вам по-преж нем у придется перебирать в ц икле три э л е ­
м ента м ассива, даже е с л и в один и л и два из н и х уже п о п а ли (и они и м ею т
значение -1). Должно сущ ествовать лучш ее решение...

вы здесь ► 159
Псевдокод

в а р и а н т тр е ти й
Можно удалить местоположение пораженной ячейки, сделав м ас­
сив меньше. Однако такие объекты не м огут изменять свой размер,
поэтому придется создать новый массив с меньшей вместимостью
и копировать в него оставшиеся ячейки.
w e ^ ccugco

Массив locationCells
до того, как прои­
зошло первое попа­
ГоГ
5 Т°'зиции
T V * ' ш
Ъ°-П>3о&нпелЬскиа хос с„
дание.
° 9 *>й ячеек ( 4 5 *6 ) ^ ^

Массив IocationCells
после того, как
ячейка 5 с индексом
1 была поражена.

-PoM-fionC^C "Р и е и н а л ,и Ш «геи?

“Третий вари ант Дудет куда лучше, если массив см ожет уменьшаться. Нам не придется
со зда ва ть ио&ый массив меньшего размера, копировать оставш иеся значения
и переопределять ссылку.

Оригинальный псевдокод для ч а сти Жизнь сразу наладится, если мы


м етода сЬескУоиг$сЦО: изменим псевдокод:

ПОВТОРЯЕМ то же самое с каждой ячейкой массива. ■ ПОВТОРЯЕМ ю же самсе с оставш им ися ячейками.

/ / СРАВНИВАЕМ ход пользователя с местоположением клетки. / / СРАВНИВАЕМ ход пользователя с местоположением клетки,

ЕСЛИ ход пользователя совпал. ЕСЛИ ход пользователя совпал,

ИНКРЕМЕНТИРУЕМ количество попаданий. —— — |ч ^ УДАЛЯЕМ эту ячейку из массива.

/ / ВЫЯСНЯЕМ, была ли это последняя ячейна. / / ВЫЯСНЯЕМ, была ли это последняя ячейка.

ЕСЛИ количество попаданий равно 3, ВОЗВРАЩАЕМ «Потопил.. ■ ЕСЛИ масеяе теперь пустой, ВОЗВРАЩАЕМ «Потопил..
ИНАЧЕ потопления не произошло, значит, ВОЗРА1ЦАЕМ «Попал.. ИНАЧЕ потопления не произошло, значит, ВОЭРАЩАЕМ «Попал-.

КОНЕЦ ВЕТВЛЕНИЯ КОНЕЦ ВЕТВЛЕНИЯ


ИНАЧЕ пользователь не попал, значит. ВОЗВРАЩАЕМ «Мимп«. ИНАЧЕ пользователь не попал, значит. ВОЗВРАЩАЕМ «Мимо».

КОНЕЦ ВЕТВЛЕНИЯ КОНЕЦ ВЕТВЛЕНИЯ


КОНЕЦ ПОВТОРЕНИЯ КОНЕЦ ПОВТОРЕНИЯ

160 гла&а 6
Знакомьтесь с Java АР!

Если бы мне удалось найти


f массив, который будет сжиматься,
когда я из него что-либо удалю. И такой,
чтобы не приходилось перебирать все его
элементы, а можно было просто спросить,
содержит ли он нужное мне значение.
И пусть бы он позволял забирать элементы,
даже если мне неизвестно, в какой ячейке
"1 они находятся. Это было бы просто
А сказочно. Ах, мечты,
мечты...

вы здесь > 161


Когда массивов недостаточно

П роснитесь и лочу&ст&уйте дух ^и^диотеки


С ловно по во лш еб ству, та к о й м ассив д е й ств и те л ь н о п о яви л ся.

Но э то не со всем м ассив — э то ArrayList.

Э то к л а с с и з ста н д а р тн о й б и б л и о тек и Ja v a (A P I).

Java Standard Edition (версия Java, с которой вы сейчас работаете; поверьте, вы бы


знали, если бы это была Micro Edition, предназначенная для небольших устройств)
поставляется с сотнями готовых классов. Это похоже на код, который мы подгото­
вили для вас, где стандартные классы уж е скомпилированы.

Это значит, что их не нужно перепечатывать.

П р о сто и сп о л ь зу й т е их.
A rra y U st

O bject-
ld d l0So ^ - n H c o K O a p a« - P
Один, из .множества
классов б оиаПисщеке id e x ) энному иидансУ-
Jd v a Аожетпе
Применять его б сбоем , внутри A " « LW l-
,emove(Obiec. ^ m ) o6wRT (ес„„ ОЙ—
Коде как соЗагцбеннЫи
класс. Уваляет у « з а ИноТО

Возераи;ае нТов.
\sEW ptyO иие если список не с о д е Р ^ тЭ ^
Примечание: Мещоо
adtKObjeci е-Сетг)) на самом Возвра1ДаеТ ' ГО в параметре пи6°
деле б(лгл5Цтг\ не тпак ^ e x O n O b ie c ^ c o ^ n e p e P - - -
Просто, как М1я здесь Возвре,ЭЩ ткущий момент.
показали. Позже М(л еш,е В списке на
элементов
беркемсЯ к его реалЬной Й1е11 ,в р а « а л « ° " '" ,еС,в0 по индексу •
берсии. А покад^/майкпе сейнас иахоДИтСЯ
о нем как о ме-уподе асЫО, g e tlin tin d e * ' . „ г ноторы*
Принимакхдем о5ъеюп.
Ге р е Р -н о ы уо ^ -^ '
КотлорЫй б(л хо>питпе
U st.
доЗаеикцЬ. WW030«

>П°

162 глава 6
Знакомьтесь с Java API

Несколько примеров использования ArrayUvt

ско5кллли. ознлчаетп ^
f f i Создаем один такой

(D
A r r a y L i s t < E g g > * m y L i s t = n e w A r r a y L i s t < E g g > () ;

Кладем в него что-нибудь: _


.«•acssi"
АгГ<^ пм^оа
E g g s = n e w E g g () ; 'Щ &г —
TeneobA m jU s ^ n o g fo c ^ .^ o S U
т• . , .. . б/лестг\ит(\о cSbeiOR %
m y L is t.a d d (s ) ;

Кладем в него еще что-либо


Egg b = new E g g ( ) ;
Л
С Х е 1 опщЬуе^ ^
m y L i s t .a d d ( Ь ) ;

Щ) Выясняем, сколько элементов в нем хранится: AnayUst храншпэ^ oSbeK^a. поэт^омч)


in t th e S iz e = m y L i s t . s i z e () ; £ —^ MeT(\oQ s»zeO ^

firr^Usi je u c ^ eA R O q f » * ™
) Выясняем, содержит ли он что-либо: на ко-торЫД с с ы л а е м с я s, по 0 j

b o o l e a n i s In = m y L is t .c o n t a in s (s ) , conWmsO fo3ep^ e 4 tru e -

^ й* Г Ч Ш
(б) Выясняем, где хранится элемент
" 0 * - ” ° * * * » . " ‘r t u « i W w * Гидеч
(то есть его индекс): / хот(\Я o S b e m н а ко^.ор 1
i n t i d x = m y L i s t .in d e x O f< b ) ; $mopbiM 6 списке.

Выясняем, не пустой ли он: Он w h o не пуатой. поэтом^


b o o le a n e m p t y = m y L i s t . is E r a p t y ( ) ; tT ' isbnptyO ~ ‘

Эй, с/лотг\ри’УГ|е — он. у/ДенЬшиЛсЯ!


(D Удаляем из него что-нибудь:
m y L i s t . rem o ve( s ) ;

вы здесь ► 163
Когда массивов недостаточно

. Н аточите свой карандаш Заполните таблицу, глядя на код слева и подбирая его аналог
для обычных массивов. Скорее всего, у вас не получится избе­
жать ошибок, поэтому просто попытайтесь угадать.

Afrraytfst Обычный массив

ArrayList<String> myList = new


Siring [] TTtyUsi = n e w String[2]:
ArrayList<String> ();

String a = new String("Ура");


String d = n e w Siring( Vpd*)s
myList.add(a);

String b = new String("Лягушка");


Siring b = n e w SiringС Л я г ^ ш к ^ ’');
1 . __ ..
myList.add(b);

int theSize = myList.size();

Object о = myList.get(1);

myList.remove(1);

boolean isln = myList.contains(b);

164 плава <5


Знакомьтесь с Java API
Э т о не
глупые Вопросы
_ jQ Р Л ЗОН А^ЛЧМ^кГЁ?
я э ы к л & AYA
Д а, A rray L ist — это
Интервью этой недели:
к р у т о . Н о к а к я м о г з н а т ь о его
* ур ArrayList о массивах
сущ ествован ии ? HeadFirst: Итак, объекты ArrayList — это что-то вроде массивов, правильно?
ArrayList: Только в их мечтах! Слава Богу, я объект.
HeadFirst: Но если я не ошибаюсь, массивы — это тоже объекты. Как и другие
U . На самом деле вопрос дол­
объекты, они обитают в куче.
жен звучать так: «Как мне узнать,
что находится в API?» Умение Anaylist: Конечно, массивы находятся в куче, по они лишь пытаются быть
работать с библиотекой — ключ похожими на ArrayList. Они подражатели. Объекты обладают состоянием
к вашему успеху в качестве Java- и поведением, правильно? Здесь нс может быть двух мнений. По пробовали
ли вы когда-нибудь выбывать метод из массива?
программиста. Кроме того, она
позволяет создавать програм­ HeadFirst: Теперь, когда вы об этом упомянули, я понимаю, что никогда так
мное обеспечение без особых нс делал. Но, в любом случае, какой метод мне вызывать? Меня волнуют
трудозатрат. Вы удивитесь, сколь­ только методы тех объектов, которые я поместил в массив. И я могу исполь­
ко времени можно сэкономить, зовать синтаксис массива, чтобы добавлять и удалять из него разные эле­
менты.
если кто-то уже сделал за вас
тяжелую работу, и остается самая ArrayList: Разве? Вы хотите сказать, что на самом деле удаляет е что-либо из
интересная часть. массива? Где они вас готовят ,в Macjava?
Но мы немного отвлеклись. Если HeadFirst: Конечно, я могу взять что-либо из массива. Я пишу Dog d *
говорить коротко, то некоторое
dogArrayl 1] и получаю из него объект Dog но индексу 1.
время придется потратить на из­ ArrayList: Хорошо, я попытаюсь говорить медленно, чтобы вы могли уследить
учение стандартных API. Если вам за ходом моей мысли. Вы не удаляете тот объект Dog из массива. Все, что вы
нужен подробный ответ, то вы делаете, — создаете копию ссылки на объект Dog и присваиваете ее другой
найдете его в конце этой главы. переменной типа Dog.
HeadFirst: Теперь я понимаю, к чему вы клоните. Нет, я фактически не уда­
Л ). ляю объект Dog из массива. Он все еще там. Но, мне кажется, я могу легко
• Это с е р ь е з н а я п р о б ­ присвоить е ш ссылке null.
л е м а . М ало т о го ч то я д о л ­
ArrayList: Я первоклассный объект, поэтому поддерживаю методы и на самом
ж ен з н а т ь о с у щ е с т в о в а н и и
деле могу, например, удалить из себя ссылку Dog, а не просто присвоить ей
A rrayL ist в н у т р и б и б л и о т е к и
null. И я могу динамически изменить свой размер. Попробуйте заставить
Ja v a , н о и, ч то е щ е в а ж н е е , массив сделать то же самое!
м н е н е о б х о д и м о п о м н и т ь , что
A rrayL ist в ы п о л н я е т и м е н н о 7е HeadFirst: Ничего себе! Не хотелось поднимать эту тему, по ходят слухи, что
ваши заслуги очень преувеличены и вы лишь менее эффективный массив.
з а д а ч и , к о т о р ы е н у ж н ы ! Как
Говорят, что вы простая обертка для массива, добавляющая ему такие спо­
ж е м не перейти от необходи ­
собности, как изменение размера, которые я должен писать сам. И раз уж об
м о с т и ч то -то с д е л а т ь к сп о со б у этом зашла речь, отмечу, что вы даже пе можете хранит ь примитивы] Разве
в ы п о л н и т ь э т о с п о м о щ ь ю API? это нс существенное офаничение?
ArrayList: Не могу поверить ,что вы купились на это. Нет, я пе просто мепее
эффективный массив. Иногда бывают ситуации, в которых массив может
^ « Теперь вы действительно оказаться слегка быстрее меня для одной и гой же задачи. 11о стоит ли отка­
уловили суть. Дочитав книгу, зываться от всех моих достоинств, чтобы получить этот незначительный вы­
вы уже будете хорошо ориен­ игрыш? Л что касается примитивов, конечно же, можно помешать их внутрь
тироваться в языке и понимать, ArrayList, используя простые классы-обертки (более подробно об этом вы
как пройти путь от постановки узнаете в главе 10). В Java 5.0 такое упаковывание (и распаковывание, ког­
задачи до ее решения, созда­ да вы получаете примитив обратно) происходит автоматически. Я знаю, что
вая минимум кода. Потерпите с примитивами быстрее работает массив, так как ему не нужно их упаковы­
еще немного — мы начнем вать н распаковывать, но... кто в наши дни всерьез пользуется примитивами?
обсуждать этот вопрос в конце Ох, вы только взгляните на время! Я о п а л и в а ю на сеанс пилатеса .Погово­
текущей главы. рим об этом еще в следующий раз.
вы здесь > 165
Разница между ArrayList и массивом

Сравнение ArrayUst с обычным массивом

AfrrayUst Обычный массив

ArrayList<String> myList = new String [] myList new String[2];


ArrayList<String>();

String a = new String("Ура"); String a « new String("Ура”);


myList .add (a) ; myList[0] = a;

String b = new String("Лягушка"); String b = new String("Лягушка");


myList.add(b); myList[1] = b;

int theSize = myList.size() ; int theSize =« myList.length; _ - —■


—\

Object о = myList.get(1); String о = myList [1]; \ 3.4uKA*rff'c5'‘

myList.remove(1) ; myList [1] = null; \

boolean isln = myList.contains(b); boolean isln = false;

for (String item : myList) {

if (b.equals(item)) {

isln = true;

break;

Обратите внимание, что с ArrayList вы Работая с массивом, вы применяете специ­


работаете, как с объектом соответствующе­ альный синтаксис (такой как miList[0] =
го типа, вызывая старые добрые методы из foo), который больше нигде не употребля­
старого доброго объекта и используя старый ется. Хотя массив и является объектом, он
добрый оператор доступа. обитает в собственном необычном мире.
Нельзя вызвать ни один его метод, вам
доступна всего одна переменная экземпля­
ра — length.

166 глава 6
Знакомьтесь с Java APi

Срз&иеиие ArrayUst с обычным мзсси&ом

ф Обычный массив в момент Массивы используют


создания должен знать свой специальный синтаксис,
размер. который в Java больше нигде
Используя ArrayList, вы каждый раз просто не применяется.
создаете объект соответствующего типа. Но в случае с ArrayList мы работаем с обыч­
Объекту все равно, большим он должен быть ными Java-объектами, которые не имеют
или маленьким, потому что он увеличивается особого синтаксиса.
и уменьшается по мере добавления
m y L i s t [1 ]
и удаления объектов.

new String [2] скоЗки [] - Элемент спеи^тЬного


cuWiUcucu. испоЛ^еМогс ^оДЬко для /Мсси«о«.
new ArrayList<String>()
KeoSxoguMocYnu В Java 5.0 класс A rrayList
параметризован.
рЗ^Мер(ксщЯ при Ж е/taKuu й л
Аюжег^е Эщо оаеяа^Ь). Мы сказали, что, в отличие от массивов,
При добавлении объекта ArrayList не имеет специального синтаксиса.
в обычный массив нужно Но у него есть кое-что необычное, появивше­
присвоить ему конкретный еся в Java с версией 5.0 Tiger — это п ар а м ет ­
индекс. р и зо ва н н ы е типы.
И ндекс долж ен бы ть в промежутке от нуля до ArrayList<String>
числа, м еньш его , чем длина м а сси в а .
myList[1] = b; <strin g ^ £ у&ло&пх скоЗкдх - Зщо тпипо&й сюгучеюь
Лrrd\/List< S irin g > однцчдетг) «список оЗоектпоь S irin g *
индекса.
(XArrgyLis1 <0 og> Читпиетг.сЯ кйк «список o5 beic*no£ Dog».
Д о версии 5.0 в Java не было возможности
Если этот индекс выходит за границы масси­ объявлять тип сущностей, которые должны
ва (например, массив объявлен с размером 2, храниться в ArrayList, поэтому с точки зре­
а теперь вы пытаетесь присвоить что-нибудь ния компилятора все экземпляры ArrayList
индексу 3), то во время выполнения програм­ представляли собой разнородные коллекции
мы будет выдана ошибка. объектов. Но теперь, используя синтаксис
<типУказываетсяЗдесь>, можно объявить
С ArrayList вы можете указать индекс через
и создать ArrayList, знающий (и ограничива­
метод add(an.Int, anObject) или просто напи­
ющий) типы объектов, которые он способен
сать add(anO bject), и объект увеличит свой
хранить. Мы подробно обсудим параметри­
размер, чтобы вместить новый элемент.
зованные типы, когда дойдем до коллекций,
myList.add(b); а пока не забивайте себе голову синтаксисом
с угловыми скобками < > , который вам будет
be3 ^SKCd. встречаться при использовании ArrayList.
Просто помните, что этот способ заставляет
компилятор допускать для ArrayList только
конкретный тип объектов (в угловых скобках).

вы зд есь ► 167
Код класса DotCom, содержащий ошибку
Псевдокод Тестовый
«од

Исправим кос) класса VotCom

Вспомните, как вы глядит версия с ошибкой.


/М* цзмвнмли -том,
public class DotCom {
OocCo^Smf W S ' ^ Z o w b в n o i b - ^ гллве'
;Ж,е K03 . Konft\opl?ui
int[] locationCells;
int numOfHit.s = 0;

public void setLocationCells(int[] Iocs) (


locationCells = Iocs;
}

public String checkYourself(String stringGuess) {


int guess = Integer.parselnt(stringGuess);
String result = "Мимо";

for (int cell : locationCells) {


if (guess
у ____ ^CC^°ШЛо не >*,

K<*H n o g g o ,^ йж$ я и лгоо


inOrU

ро.чее. Яуе й
Я-Чейка
break;
)
} / / e£OC-.j .ИМ Via М
Л

if (numOfHits == locationCells.length) (
result = "Потопил";
}
System.out.println(result);
return result;
) / / Ko^eii м-5тс-да
} ■: ■ •■

168 гл а в а 6
Знакомьтесь с Java API
Псевдокод Яйстоеый
'fp&icdijf! •-4 -

Новый и улучшенный класс 'PotCom

НоА

/^ и*5' ***
import java.util.ArrayList;

public class DotCom {


0 ***« » * « J ?
private ArrayList<String> locationCells; в ил A ravU sl. w *
i i p r iv a te i n t numOfHits; ft y * * * e *
/ / сейчас это нам не нужно o b e r a f e S tn n g .

public void setLocationCells (ArrayList<String> loc> I


locationCells = loc; йойое u
tAdYCftA-

public String checkYourself (String userlnput) ( . у.c4 ^ п д а л а х ее

String result = "Мимо"; . " Е с л и ее


мноеКС.Если е е г—
кеТС1

к: Г -mJexOfO &>3« Г ^ е т *•
int index = locationCells.indexOf(userlnput);
^e/fu индекс & rt
if (index >= 0) { ^ ---------- -'’ ^ :1^ а ^ ъ ' 2 Г&КНу1ю-
locationCells .remove (index) ; *_6*списке
— 'w3”l0^ » w s e A le e .

_ Е с л и сп и сок Ч ^ о й ,
if (locationCells.isEmpty()) { ЗНДЧШГ,. Зтцо ?ЬйЛо
result - "Потопил";
роковое poridqdKue!
} else {
result = "Попал";
} // Конец if

} // Конец внешнего if

return result;
} // Конец метода
} // Конец класса

&ы з д е с ь > 169


Создание класса DotComBusf

Создадим настоящую игру


«Потопи с а й т »
Мы работали над упрощенной версией, но теперь
создадим полноценную игру. Вместо единственного
Вам предстоит создать
ряда мы будем использовать сетку и вместо одного игру «Потопи сайт» с доской
объекта DotCom задействуем сразу три. 7 x 7 и тремя «сайтами»,
Цель: потопить все «сайты» компьютера за мини­ каждый из которых за­
мальное количество попыток. Вы будете получать нимает три ячейки.
баллы в зависимости от того, насколько хорошо
играете.
Подготовка: при загрузке программы компьютер
разместит три «сайта» на виртуальной доске (7 x 7 ). Фрагмент игрового диалога
После этого вас попросят сделать первый ход.
File Edit Window Help Sell
Как играть: вы пока не научились создавать GUI
%ja y a BotComBuBt,
(графический пользовательский интерфейс), по­
этому данная версия будет работать в командной Сделайте ход АЗ
строке. Компьютер предложит вам ввести предпо­ Мимо
лагаемую ячейку в виде АЗ, С5 и т. д. В ответ на э го
Сделайте ход В2
в командной строке вы получите результат — либо
«Попал», либо «Мимо», либо «Вы потопили Pets,
с о т » (или любой другой «сайт», который вам Сделайте хфд С4
посчастливилось потопить в этот день). Как только
вы отправите на корм рыбам все три «сайта», игра Ми*$Р
завершится выводом на экран вашего рейтинга. а Сделайте Хо ц р2
- >V%
J*14,1
КаЖоаЯ сек и м *
Доска /х/\ а ячейка*- Попал . ■. ' .y-V.Ii

А
В
е
ОЙ! Вы потопили P ets.com
С I
<ч По т о п и л
D Pi*S.Cf т _______

Е
F

AsKM e.com
_________
0 1 2 3 4 5 Попал
Сделайте ход G5
^ Начинаемся с нуля, как
Ой! Вы потопили A sk M e .co m
^массивы, в Java.
п о гл а в а 6
Знакомьтесь с Java API

Что нужно изменить? Продолжим улучшать класс


DotComBust...
У нас есть три класса, в которые нужно вне­ © Разместим все три «сайта» на сетке
сти изменения: DotCom (раньше назывался вместо единственного ряда. Этот этап
DotCom Sim ple), игровой класс (D otC oraBust) заметно усложнится, если понадобится
и вспомогательный игровой класс (о нем мы на размещать объекты DotCom случайным
время забудем). образом. Не углубляясь в математику,

О Класс DotCom
добавим в заранее подготовленный класс
GameHelper алгоритм для задания «сай­
© Добавим переменную пате для хранения там» местоположения.
имен «сайтов» («Pets.com», «Go2.com» © Будем проверять ход пользователя на
и т. д.). При потоплении каждый «сайт» всех т рех « са й т ах», а не на одном.
сможет вывести на экран свое название
© Продолжим играть (то есть принимать
(см. результат на предыдущей странице).
ходы пользователя и проверять их на
0 Класс DotComBust (игра) оставшихся объектах D otC om ) до тех пор,
пока не ост анет ся ни одного ж ивого
© Создадим т ри «сайта» вместо одного. «сай т а».
© Дадим каждому из них имя. Вызовем © Выйдем из метода main. Мы не усложня­
сеттер для каждого экземпляра DotCom ли метод main, просто чтобы... сохранить
и присвоим с его помощью имя переменной его простым. Но в реальной игре хотелось
экземпляра п ате. бы сделать его другим.

. игроком И P q j
—--------------- - < 1 ^

Три класса:
DotComBust DotCom GameHelper
1
Игровой к л а с с . О бъ екты В спом огательны й f
Создает объекты Г DotCom . класс {заранее
DotCom, полу- Знают имена подготовленный).
чает пользоеа- и местополо- Знает, как принимать
тельский ввод. * жения «сайтов» 1 пользовательский
играет, пока все и умеют прове ввод из командной
«сайты» не будут рить пользова- строки и размещать
потоплены. тельский ход на «сайты» на доске.
попадание.
L — ------- — - J

Кроме того, созда­


ны четыре объекта
ArrayList: один для
DotComBust и по
одному для каждо­
го объекта DotCom.
GameHelper

вы зд есь ► 171
Подробная структура игры

Ч то делает каждый элемент &игре


'PotCom'&USt (и &какой момент)

Метод main() класса


Экземпляры DotComBust создсет
объект DotComBust,
отвечающий за весь
игровой процесс.
Объект
DotComBust

Экземпляры

Объект
GameHelper DotComBust (игра) со­
здает экземпляр класса
GameHelpei— объект,
который поможет игре
Объект выполнять с в о ю работу,
DotComBust

Объект DotComBust созда­


ет экземпляр ArrayList,
который будет хранить три
Объект
объекта DotCom.
GameHelper

■Уде*
Объект
DotComBust

Объект A rrayList (для


хранения объектов
DotCom)

172 гл а в а 6
Знакомьтесь с Java API

Объект DotComBust
создает три объекта
DotCom (и помещает
их в ArrayList)
Объект ,
б а те Helper

Объект
DotComBust

DotComBust запрашивает DotComBust выдает каждому объекту


у вспомогательного объекта
DotCom отдельный адрес (с помощью
(GameHelper) местоположе­ вспомогательного объекта) вида А2, В2
ние «сайта» (делает это три
и т. д. Каждый объект DotCom помещает
раза, по одному для каждо­
свои три ячейки в ArrayList.
го объекта DotCom). гпг,ожение;
Объект
ArrayList
Объект (для хране­
SameHelper ния ячеек
«сайта»)

Объект
itCotn
DotComBust _

Объект
Объект A rrayList для ArrayLisI
Объект
хранения объектов
DotCom
DotCom
DotComBust запрашивает у вспо­ DotComBust перебирает список «сайтов»
могательного объекта ход поль­ и просит каждый из них проверить пользова­
зователя (вспомогательный объ­ тельский ход на совпадение. DotCom проверя­
ект просит пользователя ввести ет ArrayList с адресом и возвращает результат
данные и получает («Попал», «Мимо» и т. д.).
их из командной
строки). Объект
ArrayList
Объект
r, ^ r (дляхране-
GameHelper
■ ния ячеек
«сайта»)
Объект
Объект ArrayList
DotComBust

И вот как проходит игра... По-


_ _ W . Объект
лучаем пользовательский ввод, Объект ArrayList для
Объект Э ) A rrayList
проверяем DotCom на совпадение хранения объектов
DotCom
и продолжаем, пока все «сайты» DotCom
не будут потоплены.
еы здесь >
Класс DofComBus! (игра)

DotComBnst
ПсеЮокоЭ Зля настоящего класса 'PotCom'pust
GameHelper helper
ArrayListdotComsList
int numOfGuesses Класс D otCoinBust выполняет три главные задачи: подготавливает игру,
играет с пользователем, пока не будут потоплены все «сайты», и заверша­
setUpGamel) ет игру. Хотя для этих задач можно было назначить три отдельных мето­
startPlayingf) да, мы разбили второй пункт (игра с пользователем) на два метода, чтобы
повысить модульность. Методы с меньшими размерами лучше поддаются
checkllserGuessO
тестированию, отладке и редактированию кода.
finishGamel)

ОБЪЯВЛЯЕМ переменную helperи присваиваем ей экземпляр класса GameHelper.


ОБЪЯВЛЯЕМ переменную dotComListи создаем для нее экземпляр ArrayList, который
Объявление будет хранить список объектов DotCom (изначально три).
переменных ОБЪЯВЛЯЕМ целочисленную переменную для хранения количества ходов пользователя
(чтобы иметь возможность вывести счет в конце игры). Назовем ее numOfGuesses
и при­
своим ей О.
ОБЪЯВЛЯЕМ метод s etUpGamef), предназначенный для создания объектов DotCom и при­
своения им имен и адресов. Он также выводит пользователю краткие инструкции.

Объявление ОБЪЯВЛЯЕМ метод startPlayingf), который запрашивает у пользователя ход и вызывает


метод checkllserGuessO. пока все объекты DotCom не выведены из игры.
методов
ОБЪЯВЛЯЕМ метод checkllserGuessO, который просматривает все остальные объекты
DotCom и вызывает каждый объект DotCom метода checkYourself().
ОБЪЯВЛЯЕМ метод finishGam ef). который выводит на экран сообщение об успехах пользо­
вателя, основываясь на том, за сколько ходов тот потопил все объекты DotCom.
МЕТОД: voidsetUpGamef)
// Создаем триобъекта DotCom и назначаем имимена.
Реализация СОЗДАЕМ три объекта DotCom.
методов УСТАНАВЛИВАЕМ имя для каждого экземпляра DotCom.
ДОБАВЛЯЕМ объекты DotCom в dotComList(ArrayList).
ПОВТОРЯЕМ это с каждым объектом DotCom массива dotComList.
ВЫЗЫВАЕМ метод placeDotComf)из вспомогательного объекта, чтобы получить
случайно выбранное местоположение для этого «сайта» (три ячейки на доске 7x7,
расположенные вертикально или горизонтально).
УСТАНАВЛИВАЕМ местоположение каждого «сайта» исходя из результатов
вызова метода placeDotComf).
КОНЕЦ ПОВТОРЕНИЯ
КОНЕЦ МЕТОДА

174 гл а в а б
Знакомьтесь с Java API

Продолжение реализации методов:

МЕТОД: voidstartP/ayingO
ПОВТОРЯЕМ до тех пор, пока существует хоть о д и н объект DotCom.
ПОЛУЧАЕМ пользовательский ввод, вызвав вспомогательный метод
getUserlnput().
ОЦЕНИВАЕМ ход пользователя с помощью метода checkUserGuessf).
КОНЕЦ ПОВТОРЕНИЯ
КОНЕЦ МЕТОДА
МЕТОД: voidcheckl/serGuess(StringuserGuess)
// Выясняем, было ли попадание в один из«сайтов* (или его потопление).
ИНКРЕМЕНТИРУЕМ количество ходов пользователя в переменной numOfGuesses.
УСТАНАВЛИВАЕМ значение «Мимо» для локальной строковойпеременной result, предполагая,
что пользователь промахнулся.
ПОВТОРЯЕМ это с каждым объектом DotCom в массиве dotComList.
ОЦЕНИВАЕМ ход пользователя, вызывая метод checkYourself() из объекта DotCom.
УСТАНАВЛИВАЕМ результат значения «Попал» или «Потопил», если потребуется.
ЕСЛИ результат равен «Потопил», то УДАЛЯЕМ DotCom из dotComList.
КОНЕЦ ПОВТОРЕНИЯ
ВЫВОДИМ пользователю значение переменной result.
КОНЕЦ МЕТОДА

МЕТОД: void finishGame()


ВЫВОДИМ сообщение о конце игры, затем:
ЕСЛИ количество ходов маленькое,
ВЫВОДИМ поздравительное сообщение.
ИНАЧЕ
ВЫВОДИМ насмешливый вариант сообщения.
КОНЕЦ ВЕТВЛЕНИЯ
КОНЕЦ МЕТОДА
_ Н ато чите свой карандаш

Как мы перейдем от псевдокода к реаль­ вы протестируете и напишете в первую


ной программе? Напишем тестовый код, очередь? Попробуйте составить псевдокод
а затем начнем проверять и достраивать для набора тестов. Простого алгоритма
методы бит за битом. В этой книге мы или даже списка ключевых моментов будет
больше не будем показывать вам тестовый достаточно для этого упражнения. Но, если
код, поэтому вам самим придется поду­ вы хотите попробовать написать насто­
мать, какими сведениями нужно обладать ящий тестовый код (на языке Java), смело
для проверки этих методов. Какой метод делайте это.

вы з д е с ь > 175
Код класса DotComBust (игра)
Н аточите с&ой
Псевдокод карандаш

import java.util.*;
Д о б авы с при­
public class D otC om B u sI: {
м ечания и к о д у
сам о сто я те л ь н о !
('private GameHelper helper = new GameHelper () ;
© • ! private ArrayList<DotCom> dotComsList = new ArrayList<DotCom>О ; П о дб ер и те и х
( private int numOfGuesses = 0; в н и зу стр ан и ц ы
д л я со о тв е тств у ­
private void s e t U p G a m e { ) { ю щ их уч а стк о в
// Создадим несколько "сайтов" и присвоим им адреса к о д а , пом ечен­
DotCom one = new DotComO; н ы х ц иф р ам и.
У к аж и те ц и ф р ы
one.setName("Pets.com"); р яд о м с п о д х о д я ­
DotCom two = new DotComO; щ им и пр им еча­
two.setName("eToys.com"); ниям и.
DotCom three = new DotCom(); К аж дое при­
three.setName("Go2.com"); м еч ани е б у д е т
dotComsList.add(one); и сп о л ь зо в ать ся
один р аз.
dotComsList.add(two);
dotComsList.add(three);

System.out.println("Ваша цель — потопить три "сайта".");


System.out.println("Pets.com, eToys.com, Go2.com");
System.out.println("Попытайтесь потопить их за минимальное количество ходов");

for (DotCom dotComToSet : dotComsList) { ©


ArrayList<String> newLocation = helper.placeDotCom{3); ©
dotComToSet.setLocationCells(newLocation);
} // Конец цикла
} >! Конец метода setUpGame

private void s t a r t P l a y i n g () {
while(!dotComsList.isEmpty())
String userGuess = helper.getUser Input ("Сделайте ход'1); 0
cheekUserGuess(userGuess); 0 )
} I t Конец while
finishGame () ; (5J)
) i / Конец метода startPlaying method

TIoAviMdeM ho/lb^o^cnfneilb- у вспоМогатпе


ский $ Ц . ^ оЪЪетЛ ^9рес «cdUTnd*.
Покоряем с одЪеющоМ
r'jy ' Do’tCoTT) б СПМСК£-
Pta& gu* ч*, о5ып
ереС<2 ? ^ ° 5Ъедвд D°T o ™ . ~
,^нстпр\кциизля ние, Ко^ ' ^ ^ecvriorioyjoofce- d,ecfc ^crG uess. 5
ПолКаделх. °*

_ Й * З Ы & е* к а ш « ^ о о А Г До n°j>. П°>М список


^ ' 1 „ ,, п1ЪоKind DoiConh, 9^еМ ооЪект)0« DoiCon) ке
п
о
т«A n o
176 гл а в а 6
Знакомьтесь с Java API
Псевдокод Тестовый
«од Что бы ни
случилось, не
переворачивайте
private void checkUserGuess (String userGuess) { страницу, пока
не закончите это
numOfGuesses++; @
упражнение!
String result = "Мимо"; $2
На следующей
for (DotCom dotComToTest : dotComsList) {
странице наша
result = dotComToTest.checkYourself(userGuess);(и) версия.
if (result.equals("Попал")) {
break; (g)
*
if (result.equals("Потопил")) (
dotComsList.remove(dotComToTest); Q
break;
)
) // Коней r :-r
System.out.println(result);
} if KOH'SI.! *4v»TO«*S

private void fin±shGame() (


System, out .println ("Все "сайты" ушли ко дну! Ваши акции теперь ничего не стоят.");
if (numOfGuesses <= 18) {
System, out.println ("Это заняло у вас всего" + numOfGuesses + "попыток.");
System, out .println ("Вы успели выбраться до того, как ваши вложения утонули.");
} else {
System.out .println ("Это заняло у вас довольно много времени. "+ numOfGuesses + "попыток.");
System.out .println ("Рыбы водят хороводы вокруг ваших вложений.");
}
} // Конец метода

public static void m a in (String[] args) {


DotComBust game = new DotComBust();t :Л
game .setUpGame () ;
game.startPlaying() ;
) f f Конец метод?»

Т1о&порЯе/Л Этг)0 3/1Я ёсех о5Ъеют)о£ __ Ы о у и м улЯ По/тЬ^о^и-


г DotCoTT» £ списке. т ^ е-пя pe^yib-na-vn.
__.в х о д и м с о о б щ е н и е о -щом, '
_ Прише/i конец, yimk 4 vrjo уо^ лЯем е г о ия
списка «саСЫр*» и ^ кик ^олЬ^оёсщелЬ проще/) ___Говорим игровому
игрУ- о$Ъекгг\у Г)одг<що-
Инкремекупир^ем количество попЬщок, Ц оораа^е^емпромдх, вищЬ игру,
Котпор(ле ege/ktn r]o/}b^Q£cXYr\s.fb.
пока не ^(ляскали о5 р<щного.

Зр^/гие «саСЬту Создаем игре


вы здесь > 177
Код класса DotComBust (игра)
Псевдокод Осотовый

мек-
import java.util.*; 05ъя8ляем u инициал
public class D o tC o m B u s t H te. которые нам

private GameHelper helper = new GameHelper();


private ArrayList<DotCom> dotComsList = new ArrayList<DotCom>();Соззлйкпе Arm\)Ust
private int numOfGuesses = 0;
ТОЛЬКО эля оЗъек^оК

private void s e t U p G a m e ( ) { DotCom-


// Создадим несколько "сайтов" и присвоим им адреса
DotCom one = new DotCom();
one.setName{"Pets.com"); Созовем кт\ри оЬъекУГ\Л
DotCom two = new DotCom();
two.setName("eToys.com"); u n oM euieM 6A rr^U st.
DotCom three = new DotCom{)
three.setName("Go2.com");
dotComsList.add(one);
dotComsList.add(two);
^ 6030 * краткие
dotComsList.add(three) ; иКст(\р^ки^1А эЛЯ
ПолЬЗо&щеЛЯ.
System.out.println("Ваша цель — потопить три "сайта".");
System.out.println("Pets.com, eToys.com, Go2.com");
System.out.println("Попытайтесь потопить их за минимальное количество ходов");

_ П о£ш >0Я<!Л с каждым о5ъеюп°м


for (DotCom dotComToSet : dotComsList) [
DotCom в списке. ^
z_-— м ЙспоЛогЛ'те.лЬкого
ArrayList<String> newLocation = helper. placeDotCom(3) ; sT цэрес
«сцйгпй».
dotComToSet.setLocationCells (newLocation) ; — B b n lu & o ..

' ЧЧО& ° 0iC° 4


} п Конец цикла «°» 1орое ^олЬко Чщо о0 Л ^ ° ЖеНие-
) У / Конец метода sec'Jpgame

private void s t a r t P l a y i n g () { Г 0rs , r


До пор. пока список объектов Outturn
while (!dotComsList.isEmpty () ) K.e стулне'Щ
Т1оД^ЧлеА\
^ н( , гю-ЛЬзп&п^вЛЬский-
String userGuess = helper.getUserlnput("Сделайте ход"); и
checkUserGuess (userGuess) ; в<__. л
uess.
) / / Конец w h ile
finishGame (); ЗЦзЫ&ем нлш мегупоэ finish6d>ne.
) // Конец метола startPlaying

178 гл а в а 6
Знакомьтесь с Java API
Псевдокод Тестовый
. ■ ffЩ ЩД Ш

private void c h e c k U s e r G u e s s (String userGuess) {


Икнремеадир^ем количество ПопЬщок. ксЩорЫе
numOfGuesses++; <------ сделал долЬЗов^т^бЛЬ.

String result = "Мимо"; х~ ПодрсАЗ^мевдеМ npo/Agx,

for (DotCom dotComToTest : dotComsList) { £


DoiCoYr\ в списке.
result = dotComToTest.checkYourself(userGuess); - TlpocuMDotCon) проверить X03
рользовдтпеля, uui,eM nondgdHue
if (result.equals("Попал")) ( (или попщоплекие).

break; Цикла fkSHbu* времени, нетп


) смысла проверять 5 ругие « Ий^1я».
^грЯуцЬуруг
if (result.equals("Потопил")) (

dotComsList. remove (dotComToTest) ; Пришел Конец, ТГ|сАК Чщо \юс1ЛЯел\


break; € г о а <3 c r 1u c K d « с д й т д о в » U Й л х о а и м
1*3 Цикли. ^

} i f Конец, for

System.out.println(result); Вы£о3 им3 т пользователя


Выёо^им соо5 их,екие
pejyib-rnd-rrp
} if Конец метола 0 ^ ола, Kdk Пользой-

private void finishGame() { ” т ” ?


System.out.println ("Все "сайты" ушли ко дну! Ваши акции теперь ничего не стоят.");
if (numOfGuesses <= 18) {
System.out .println ("Это заняло у вас всего" + nuinOfGuesses + "попыток.");
System.out.println ("Вы успели выбраться до того, как ваши вложения утонули.");
} else {
System.out.println ("Это заняло у вас довольно много времени. n+ numOfGuesses + "попыток.");
System.out .println ("Рыбы водят хороводы вокруг ваших вложений.");
}
) // Конец метода

public static void m a i n (String(] args) (


DotComBust game = new DotComBust () ; --- Сочл^=..
• О у зем и г
game.setUpGame(); гР°&й о&екщ
game.startPlaying()
-------------------------Го&~
игрокеXV 0 5 b ..
) // Конец метода
1°*°рим игровом,. _ 5. ^ ПС^ гоп^ У г 1Ь иг
РУ-
Цикл
Л ^ЛдвнЬги
ООЛ.Ченн/..-----й <*«? ии „ “й Г ™
J KHbL^ ^схннЫе). т*°®рЯтг|Ь

вы зд есь ► 179
Код класса DotCom

Псевдокод Тбстояыи
код

Окончательная версия класса 'PotCom

import java.util.*;
Иеремекн1ле экземпляра класса
public class DotCom { DoiCoTn:
. , C ЯЧ&1ДХ^А\М.,
private ArrayList<Strmg>
ArrayListcJ locationCells; ^r эПисЫб’йКХДи^и
m * . ___
Местщоположение;
" i
private String name; '■) - имя «сайтгпа*-
Секп^пвр, котг\ор1лй.
public void s e t L o c a t i o n C e l l s (ArrayList<String> loc) ---- о5ковлЯетт\
{
Местоположение
locationCells = loc;
«cached5* ( случййнЬш ^
} адрес, предосшвлЯем 1яй
Метг\одоМ p-fdceDotConfrp)
из класса 6а-упеНе?рег).
public void setName (String n) Ц — ■$аш простой сечгщер
name = n;
fW g ^ e x O fO ^ A r ra ^ U st
1
в действии] Если ход
пользователя совпал с одним
public String c h e c k Y o u r s e l f (String userlnput) { из Элементов Anrd\|Ust, тя)°
метцоа \ndex0fO веркечп его
String result =• "Мимо"; местоположение. Если нетя), 'У'П°
int index = locationCells.indexOf (userlnput) ; > indexO-j-() вернечп ~ J -
if (index >= 0) {
Применяем метгпод rernoveO U3 Arr<Xj^si
locationCells .remove (index) ; <r”
. удаления Элемента.

if (locationCells.isEmpty О ) { ИсдолЬз^еМMewog isbnpt^O, 4rno5biпроверить,


result « "П о то п и л "; все Ли адреса SbUlu разгаданЫ.
System.out.println("Ой! Вы потопили" + name + " : ( ");
} else ( T V r
result = "Попал"; 0
La
C;±E ? ^ ^ в л к ,
Плении жсай>па»
} // Конец if
) П Конец if
return result; . „

пал»
} // Конец метода
// Конец класса

180 гл а ва 6
Знакомьтесь с Java API

Супермошиые булевы выражения


До этого момента мы работали с довольно простыми булевыми Неравенства {!= и !)
(логическими) выражениями, которые применялись в циклах
Допустим, есть утверждение вида «Определенное свойство вер­
и условиях. Далее мы воспользуемся более мощными булевыми
но для всех десяти доступных моделей камер, кроме одной».
выражениями в некоторых фрагментах подготовленного кода,
который вы еще увидите. Конечно, б ы могли бы их и не заме­ i f (model != 2000) {
тить, но нам кажется, что сейчас самое время поразмыслить над
// Выполняем действия, не относящиеся к модели 2000
тем, как сделать выражения более мощными.
)
Или нужно сравнить такие объекты, как строки...
Операторы «И» и «ИЛИ» (&&, В)
i f ( {brand.equals(RXW)) {
Допустим, вы пишете метод chooseCameraO, содержащий множе­
ство правил о том, какую камеру нужно выбирать. Может быть, / / Выполняем действия, не относящиеся к марке X)
вас устроит ассортимент камер с ценой в пределах $50-1000, }
но иногда хочется более тонко ограничить ценовой диапазон.
Например, нужно указать нечто вроде:

«Если цена находится в пределах между $300 и $400, выбира­ Укороченные логические операторы
ем X». ( & & .»
Операторы && и ||, которые мы до сих пор изучали, также извест­
if ( p r i c e >= 300 && p r i c e < 400) { ны как укороченные операторы. В случае с && выражение будет
истинным, только если обе его части истинны. Таким образом,
cam era = ПХ "; если JVM видит, что левая час i. выражения && возвращает false,
) она тут же останавливается: Она даже не подумает взглянуть на
правую сторону.

То же самое происходит с оператором ||: выражение будет ис­


Допустим, вам доступно десять марок камер и по некоторым
тинно, если любая из его частей истинна. Если JVM видит, что
условиям вы можете выбрать несколько из них.
левая сторона возвращает true, то она объявляет все выражение
истинным и не проверяет правую часть.

i f (b ra n d .e q u a ls ("А") || b ra n d .e q u a ls (“В") ) ( Почему это хорошо? Допустим, у вас есть ссылочная переменная
// Выполняем действия только для марок А или В } и вы не знаете, связана ли она с объектом. Если вы попытаетесь
вызвать метод из этой нулевой ссылки (которая не указывает на
объект), то получите исключение NullPointerException. Поэтому
Логические выражения могут стать очень большими и сложными: попробуйте сделать так:

i f ( (zocm Type.equals("Оптический") && i f (refV ar != n u ll &&

(zoomDegree >= 3 £& zoomDegree <= 8)) | | re fV a r. isV alidType() ) {

(zoomType. e q u a ls ("Цифровой") && / / Выполняем действие "получить допустимый тип"

(zoomDegree >= 5 && zoomDegree <= 12))) ( }


/ / Выполняем соответствующее масштабирование Простые логические операторы (&, I)
} При использовании с булевыми выражениями операторы & и |
Если вы хотите разобраться в этом белее детально, то начните ведут себя так же, как их братья-близнецы && и ||, за исключе­
с изучения приоритетов операторов. Пока же мы рекомендуем нием того, что они заставляют JVM всегда проверять обе части
вам использовать круглые скобки, которые позволят сделать выражения. Как правило, операторы & и | применяются в других
код понятным. ситуациях, например для работы с битами.

вы здесь > 181


Готовый к употреблению: класс GomeHefper

Код, готовый Э ю вспомогательный класс для игры. Если не считать мето­


к употреблению да для приема пользовательского ввода (который предлагает
пользователю ввести данные и считывает их из командной
строки), то его главная задача состоит в создании ячеек с адре­
сами объектов DotCom. На вашем месте мы бы набрали и ском­
пилировали этот код и больше к нему не прикасались. Мы ста­
import java.io.*; рались сделать его как можно проще, чтобы вам не пришлось
import java.util.*; набирать слишком много текста, но это ухудшило читаемость
кода. Помните, что вы не сможете скомпилировать игровой
public class GameRelper j класс DotComBust, пока не наберете этот код.

private static final String alphabet = "abcdefg";


private int gridLength = 7; Примечание: Чуг)о5 (л ^dpdSoTigdinib
private int gridSize = 49; «^оГ)о/1Нитпе/1Ьн(ле оЧки»,
private int [] grid = new int(gridSize];
private int comCount = 0; Можетпе noripoSo&CVTib
« pdcxoMMeKKTiupo&iiTib»
public String getUserlnput(String prompt) ( стдроки c S^sieTrvoui.prititCPrO
String inputLine = null; в M e y r iо ^ е p j ’d c e O o iC o Y n n .
System.out.print(prompt + " "); Зтдо ^5е^итг)ЬсЯ
try (
BufferedReader is = new BufferedReader( ё тпом. Чудо Леидо^ ра5 отг)<детц1
new InputstreamReader(System.in)); fid Э к р о к е ёы ^би^икде
inputLine = is.readLine () ; ёЫ-ражениЯ с Koopgu.HdTnd.Mu.
if (inputLine.length() — 0 ) return null; «сой-упоб», котпор(ле п о з & х л Я т щ
} catch (IOException e) (
ёам « с х и т п р и т п Ь » п р и игре,
Systern.out.printIn(“IOException: " + e);
d тпокж е X )o M o z ftr\ ПроёеритдЬ
}
return inputLine.toLowerCased; рО§оупоспосо5 ностпЬ донного
Mengo^d.

public ArrayList<String> placeDotCom(int comSize) (


ArrayList<String> alphaCells = new ArrayList<String>|);
String [] alphacoords = new String [comSize]; // Хранит координаты типа f6
String temp = null; // Временная строка для конкатенации
int [] coords = new int[comSize]; // Координаты текущего "сайта"
int attempts = 0; // Счетчик текущих попыток
boolean success = false; // Нашли подходящее местоположение?
int location = 0; // Текущее начальное местоположение

comCount++; // Энный "сайт" для размещения


int incr = 1; // Устанавливаем горизонтальный инкремент
if ((comCount % 2) == 1) ( // Если нечетный (размещаем вертикально)
incr = gridLength; // Устанавливаем вертикальный инкремент
]

while ( (success & attempts++ < 200 ] ( // Главный поисковый цикл (32)
location = (int) (Math.random)) * gridSize); // Получаем случайную стартовую точку
/ / S y s t e m , c u t . p r i n t (" л р е -б у е м '' * l e g a t i o n ) ;
int x = 0; // Энная позиция в "сайте", который нужно разместить
success = true; // Предполагаем успешный исход
while (success S& x < comSize) ( // Ищем соседнюю неиспользованную ячейку
if (grid[location] = 0) ( II Если еще не используется

182 гл ава 6
Знакомьтесь с Java API

Код, готовый

в
к употреблению ТТродолжеиие кода <5гатеИе1рсг...

coords[x++] = location; // Сохраняем местоположение


location += incr; // Пробуем "следующую" соседнюю ячейку
if (location >= gridSize)| // Вышли за рамки - низ
success - false; // Неудача
I
J

if (x>0 && (location % gridLength === 0)) | // Вышли за рамки - правый край
success = false; / / Неудача
I
r

) else ( // Нашли уже использующееся местоположение


// System.out.print(“используется" * lo c a t io n ,) ;

success = false; // Неудача


}
)
} // Конец while

int x = 0; // Переводим местоположение в символьные координаты


int row = 0;
int column = 0;
/7 Systss.o ur. piifitln ( "\n“>;
while (x < comSize) (
grid[coords[x]] = 1 ; // Помечаем ячейки на главной сетке как "использованные"
row = (int) (coords[х] / gridLength); // Получаем значение строки
column = coords[х) % gridLength; // Получаем числовое значение столбца
temp = String.valueOf(alphabet.charAt(column)); // Преобразуем его в строковый символ

alphaCells.add(temp.concat(Integer.toString(row))); U0fl\
x++;
// S y stem .co t.p ria tf* co o rd • + ;;* " = " * aiphaC elis.gei ( x - i ) ) ;
. . iV
)

/V Sy$tem.out.prin t i n ;

return alphaCells;
)

вы зд есь ► 183
Пакеты API

Использование ^и^лиотеки (Java A fl)


Итак, не без п о м о щ и ArrayList вы прошли все этапы
создания игры «Потони сайт». Теперь, как и было
обещано, пришло время научиться работать с библио­
текой Java.

В Java APB классы


сгруппированы в пакеты .

Чтобы использовать класс


из A PI, нужно знать, в каком
пакете он находится.
Любой класс из библиотеки Java принадлежит
определенному пакету. У пакета есть имя, напри­
мер javax.swing (пакет с классами пользовательско­
го графического интерфейса (G U I) Swing, с кото­
рыми вы скоро познакомитесь). Класс ArrayList
находится в пакете java.util, который содержит
набор классов-утилит. В главе 16 вы узнаете много
нового о пакетах, в частности научитесь помещать
собственные классы в собственные пакеты. На этом
пока остановимся, ведь мы хотим просто приме­
нять классы, которые поставляются вместе с Java.
Использовать в своем коде классы из API легко.
Вы просто работаете с ними так, как будто сами их
написали, скомпилировали, и теперь они ждут, ког­
да вы их задействуете. Но есть одно существенное
отличие: где-то в своем коде вы должны указать
полное имя нужного библиотечного класса в виде
«имя пакета + имя класса».
Сами того нс подозревая, вы уж е используете
классы из пакета. Классы System (System .out.
println), String и Math (M ath.random ()) находятся
в пакете java.iang.

184 гл а в а 6
Знакомьтесь с Java API
Э то не а
Необходимо знать полное имя* глупые вопросы
класса, который вы хотите ф .
•Р * Почему нужно указывать
использовать в своем коде. полное ими? Это единственное
предназначение пакетов?
ArrayList — это не полное имя класса ArrayList, как
и Катя — сокращ ение от имени Екатерина. Полное имя
ArrayList на самом деле: О-• Пакеты важны по трем основ­
ным причинам. Во-первых, они
ja v a . u t il.A r r a y L is t помогают при общей организации
проекта или библиотеки. Вместо
того чтобы смешивать классы
\ Л в одну большую кучу, их группи­
П<ЗКеуг)е1. КЛАССА
руют в пакеты исходя из функций
(например, GUI, структуры данных
или базы данных и т. д.).

Вы должны сказать iava, какой им енно Во-вторых, благодаря пакетам вы


получаете области видимости,
ArrayList хотите использовать. У вас есть которые помогут предотвратить
два варианта: конфликт, если вы и еще 12 других
программистов вашей компании
Q И М П О РТИ РО ВА ТЬ вдруг решите создать класс с одним
П ом естить оператор import в начале своего исходного ф а й л а: и тем же именем. Если у вас создан
класс Set и где нибудь еще (включая
im p o r t ja v a . u t i l .A r r a y L is t ; Java API) имеется класс Set, то вам
p u b lic c la s s M y C la s s { . . . } нужен способ сообщить JVM о том,
какой именно из этих классов вы
или пытаетесь использовать.
В-третьих, пакеты предоставляют
еще один уровень безопасности,
так как вы можете ограничить
Q НАБРАТЬ доступ к своему коду только теми
Н абрать полное имя класса в любом м е сте своего классами, которые находятся
кода. Каждый р аз, когда вы его и спользуете. в одном пакете. Всю информацию
Везде, где вы его используете. об этом вы получите в главе 16.

При объявлении и/или создании его экзе м п л яр а :


java.util.ArrayList<Dog> list = new java.util.ArrayList<Dog>();
ф: Вернемся к конфликтам
имен. Чем здесь поможет пол­
ное имя? Что помешает двоим
разработчикам дать пакету
При использовании его в качестве ти п а ар гум е н та: одно имя?
public void go (java, util.ArrayList<Dog> list) { ) jk

U • В Java включено соглаше­


ние об именовании. Если разра-
При использовании его в качестве типа возвр а1даем о го зн ачени я: ботчики его придерживаются, то
public ja v a , util.ArrayList<Dog> foo() |...) таких ситуаций, как правило, не
возникает. В главе 16 мы изучим
этот вопрос более подробно.
‘ Если только этот класс не из пакета java.lang.
е ы здесь > 185
Когда массивов недостаточно

появилась буква -------- КЛЮЧЕВЫЕ МОМЕНТЫ ^ ---------------


«х», или Что значит, когда ■ ArrayList— класс из Ja va API.
пакет начинается с javax? ■ Чтобы добавить элемент в ArrayList, ис­
пользуйте метод ad d ().
В первых двух версиях Java (1.02 и 1.1) все
поставляемые классы (другими словами, ■ Д л я удаления элемента из ArrayList приме­
стандартная библиотека) находились в пакетах, няйте removed.
начинающихся со слова java.
Среди них, конеч- но
■ Чтобы выяснить, где внутри ArrayList на­
же, всегда присутствовал java.lang— пакет, который не нужно
ходится (и находится ли вообще) элемент,
импортировать. Крометого, там были java.net,java.io,java.util
(хотя там не было класса Array List) и несколько других пакетов, используйте indexOf().
включая java.awt с классами, связанными с GUI. ■ Чтобы выяснить, пуст ли ArrayList, и сп о ль­
Были и иные пакеты, не включенные в стандартную библиотеку. зуйте isEmptyd.
Их классы известны как расширенияи делятся на две группы: ■ Если хотите получить размер (количество
стандартные и нестандартные. К первым принадлежат классы, элементов) ArrayList, используйте метод
которые компания Sun считает официальными, в отличие от
sized.
экспериментальных пакетов, пребывающих на ранней стадии
разработки или в статусе «бета». Последние могут так никогда ■ Помните, что д л я получения длины (количе­
и не попасть в официальную поставку. ства элементов) обычного массива с ле д уе т
применять п е р е м е н н у ю le n g th .
Имена всех стандартных расширений, исходя из соглашения,
начинаются со слова java,
к которому добавляется буква «х». ■ ArrayList при необходимости д и н а м и ч е с к и
Прародителем всех стандартных расширений считается библио и з м е н я е т свой размер. Он увеличивается
тека Swing. Она включает несколько пакетов, названия которых при добавлении объектов и у м е н ь ш а е т с я
начинаются с javax.swing. при их удалении.
Но стандартные расширения могут быть приравнены к перво­ ■ Тип массива объявляется с помощью т и п о ­
классным, поставляемым вместе с Java и входящим в стандарт­
в о го п а р а м е т р а , который представляет со ­
ную библиотеку пакетам. Именно это и произошло со Swing
бой имя типа в угловых скобках. Например,
начиная с версии 1.2 (которая в итоге превратилась в первую
версию из ветки Java 2). ArrayList<Button> означает, что ArrayList
способен хранить только объекты типа
«Здорово, — подумали разработчики. — Теперь все пользовате­
Button (или его дочерних классов, о чем бу­
ли Java будут иметь классы Swing и нам не придется думать об
их установке». де т рассказано в следую щ их главах).

Однако здесь таилась одна проблема, так как пакет с новым ста­ ■ Несмотря на то что ArrayList хранит объек­
тусом, конечно же, должен был иметь имя, начинающееся с java, ты, а не примитивы, компилятор автомати­
а не сjavax.Все знают, что пакеты в стандартной библиотеке не чески «уп а к уе т» (и «распакует», когда вы
содержат в своем названии букву «х», которая бывает только попытаетесь его достать) примитив в объ­
у расширений. И вот перед самым выходом версии 1.2 компа­ ект и поместит его в ArrayList (подробнее об
ния Sun наряду с другими корректировками изменила имена этой возможности будет рассказано далее
пакетов и убрала «х». В свежих книгах, лежавших на полках ма­
в книге).
газинов, описывался код Swing с использованием новых имен.
Соглашения об именовании были соблюдены. В мире Java царил ■ Классы группируются в пакеты.
порядок. ■ У класса есть полное имя, которое состо­
Все было хорошо, если не считать примерно 20 тысяч програм­ ит из его обычного имени и имени пакета.
мистов, рвущих на себе волосы. Они вмиг осознали, что это Класс ArrayList в действительности назы­
невинное изменение в именах ведет к катастрофе! Необходимо вается java.util. ArrayList.
было исправить весь код с использованием Swing! Кошмар!
■ Чтобы использовать класс из пакета (если
Представьте себе все операторы import, которые начинались
сjavax... это не java.lang). нужно сообщить Ja va его
полное имя.
В итоге, отчаявшись и потеряв надежду, разработчики убеди­
ли компанию Sun «наплевать на соглашения и спасти их код». ■ Вы можете либо указывать оператор import
Остальное — уже история. Поэтому, когда вы видите в библио­ в начале исходного кода, либо набирать
теке пакет, название которого начинается с javax,
знайте, что он полное имя класса при каждом его упоми­
появился на свет как расширение, а потом повысил свой статус. нании.

186 гл а в а 6
Знакомьтесь с Java API
Э т о не _
глупые вопросы
ф
Р
.
. Увеличивает ли оператор
- .

import размер моего класса? Добав­


ляет ли он в мойкод при компиляции
импортируемые классы и пакеты?
к
Прикрепи это1 I
Солнце светит, А
U т Вы#должно быть, программируе­ к
Ь л о шна„ благодат Г
те на языке С. Оператор import отли­ *
чается от директивы include, поэтому £
£
на оба вопроса ответ будет один — нет.
Оператор import избавляет от набора [
лишнего кода. Вам не нужно беспоко­ в
иться о том, что из-за слишком боль­
шого количества выражений импорта “ Ов ИЗ пакет а java п ' Не « и т а я
код получится раздутым или будет " е р а тор а i m p o r t в н а Л 9'РазмеЩение
медленно работать. Оператор import путь. Игнопмп
' Это легкий ИС*ОДНОг° кода -
позволяет передать Java полное имя ®ынуждены н а б и р а г ь ^ Г ^ ^ er f
класса. де применяете его/ 6 Имя Класса везде, j.

F
ф .
Р • Хорошо, тогда почему я никог­
да не импортирую класс String? Или
System? Если вы все еще этого не поняли:

(J ф Запомните, пакет java.lang


импортируется как бы заранее, без
вашего участия. Поскольку классы
в java.lang весьма основательны, вам
не нужно использовать для них полные
имена. Классы java.lang.String и java.
lang.System существуют лишь в одном
экземпляре, и Java очень хорошо осве­
домлен о том, где их искать.

ф: Должен ли я размещать свои


классы внутри пакетов? Как мне это
сделать? И могу ли я это сделать?

(].
т В реальном мире у вас будет
необходимость размещать классы
в пакетах. Более детально мы погово­
рим об этом в главе 16. А пока классы
из наших примеров будут существовать
вне пакетов.

вы зд есь > 187


изучение аи

Хорошо, когда известно что ,


Array List находится в пакете
java.util. Но как бы я смогла доду­
маться до этого самостоятельно?
Джулия, 31 год, модель

Как р аботать с A fl
Две вещи, которые вам следует знать.

О К акие классы содержатся


в библиотеке?

К ак вы узнаете о возможностях
© класса, оты скав его?

о Читаем книгу

Используем документацию
по APH в формате HTML
rMrtVvettfX,? *;OC*!V.V yn
6Д : *o;3cki-ji-

J a v a ™ 2 PUrttefm рИТЛаВГ**савCl»8%meX.» BUO&dHf MB H*lQ Jarct*3ViuJjxtf}*


SUsvUn* Ed. 5Д ИГ» МЗТ *W,S«M£l Л'Лшйзп*EdLSt)
Рвосздвз Java012 РЫГлгш Su>ndurd Edition 5.0
API Specification
Aiiaixn Ih b ifocuon! К Jbc APJ UprdOcitfcifl fwfly J t " l J fW n r» Siu-LmJ ЫЛпч> 5 0
МДОЯДО» Sen
ДЬсОлЯШп
бМСМЗДВД»
ВдоМш
ЛИЛОН^^я"

JAVA
?£fCc4>H‘,rt*c#c<*>rrv J a v a ' 2 P i a J f o r p i P n r lt u ^ o s
JДb
дa
оrea
еваP йtticw
свотriеДОва»цI }
P*.r%«tfc* the U u k t ouv*vu> «>errrse yn spf-Vi amA :
Ъгллтйя iu*vr* л sppkte n u>сршалхглгис vrih £< appin
fstaamDoa: t^xcom
-■* • • • ■ • •
Ottfcutv аУ ЫйкvlstKAtin кгся(гц:мжг istt’Xo » » 6»
Uetasi рзегосу Rtaphir» эттЛ иплге*.
40lPltS«№rt«SlM ,
РйПЦ1с<Cl.lW» fur ОЙ;*-if^CO

__ _ ■
f ил К-Чг" trJ.rrfo:<r>ml cbvc« fo: вю£&ЛЬй{ Фллhrivetfo.
.*=• -V-'nr?<•.-!!—>-1
A Desktop Quick Reference

О REILLY tX»MnMMN

188 гл а в а 6
Знакомьтесь с Java API

Читаем книгу

Листать справочник — лучший способ


изучения содержимого библиотеки
Java. Просматривая страницы, вы л ег­
ко можете обнаружить класс, который
покажется вам полезным.

juvti litit. Currency

Returned By: jauteK-DecimalFomat^CurrHicyO. java.tesl.DndmalFofmatSymibols.gatOiirencyO,


jBva.iQLNumb^wnM.getCurreflcyO. Cunency.eetinstancei)
Имя КЛ4ссс\.
Date Java 1.0
javs.util daneabie seriateabki comparable
ИМЯ ПЗКе-утуд. This d ass represents dales and times and iHs yon work with them in a sysfem-indepen-
deni way. You can create a Date by specifying the number of milliseconds from the
epoch tniidmubi GMT. January 1st, 1970) or the year, month, date, and, optionally, the
hour, minute, and second Years n c specified as the number of years since 1900 If you
rail the Date constm aor with no arguments, die Date is initialized to the current tunc
and date. The instance methods of the class allow you to gel and set the various date
OnuicrtWJ-e к т с с Л '
and rime fields, to compare dates and limes, and to convert dates to and from .string
representations /V- of Java 1.1, many of die date rnelh'Kls have been deprecated in
fnv> r i ■
! the inciluvis of the CalciKlar dan:

Date j

[Овпа=Ыс[ |Ompy,rt>:e| [Strabst-le}

puWic class Date Implements Ooneable. CompataMft, Srcalltabte {


//Public ConsIntcMs
pubic Date’)
pubic Dateflotifi Aife};
t public DatefSMcg $):
w pubic Date(nit y«ir. ini month,ini date};
t public Beta\inl ini month. ini date, ml firs, ini ляп);
i public Datefiiil year int month, inf dale, ini hfi. ini rah, inf sec):
// PropertyAnonsorMethods[Щpropertynsm)
public long getfimef}:
pubic void setTImeflong time}:
//Puhfc Alsfanse Afefbods
^ о 3 Ы fu public boolean aftedjava util. Date nhenf.
public boolean beforeyeva ulil.Dafe wfteo):
З л е л е т ч Ы . о кокоры * 12 pubic ini conparelb'iiava.utii.Date anotherDate):
/ / Methods йпрьдояй^ fanpantie
^ Поговоримnojxe). U pubic ini cantparefci(Objact o):
//Pubic Methods ОкпШеObject
и public Obiect clofleij:
public boolean equalsfODjKi d f‘:
public int liashCudof):
pubic Stniw toSlrtogO
// Deprecatedfiibh: Uethros
г public Ini gctOutw;:
a publicinlgetOayi);
i pubic Int gatHoursQ:
c pubic Ini eeiMlnates().
i public ini getMoutfef):
* pubic Int getSecondsi j .
i pubic int geOhnezoneOflsetQ;
« public int gettoari):
i putllc static long parselStn ngsj,
t pubic veld sotDatafm t dale);
< public vow setHouisfn!/kwis);
t pubic void setMlnules(in! minutes}:
t pubic void setMoettJnl пил»):

вы здесь > 189


Использование документации по Java API

© Используем документацию по A P I в формате HTML


В поставку Java входит потрясающий набор Например, в справочнике указано, что
онлайн-документов под общим названием именно принимает метод в качестве ар­
Java API. Они представляют собой часть гументов и что он возвращает. Вернемся
более объемной коллекции документов, к ArrayList. В справочнике вы можете
известной как Java 5 Standard Edition найти метод in d exO f(), который мы и с­
D ocum entation (которая может им ено­