КулЛиб - Классная библиотека! Скачать книги бесплатно 

Java. Полное руководство [Герберт Шилдт] (pdf) читать онлайн

Книга в формате pdf! Изображения и текст могут не отображаться!


 [Настройки текста]  [Cбросить фильтры]
полное
руководство

Java
10-е издание

The Complete
Reference

Herbert Schildt

Ncw York Chicago San Francisco
l,isbon l,ondon Madrid Mcxico City
Milan Ncw Dclhi San Juan
Seoul Singaporc Sydney Toronto

полное
руководство

Java
10-е издание

Герберт Шилдт

Моск ва

• Санкт-П етербур r·
2018

ББК

32.973.26-018.2.75

удк

681.3.07

Ш57

Компьютерное издательство "Диалектика"

По общим вопросам обращайтесь в издательство "Диалектика" по адресу:

info@dialektika.com, http://www.dialektika.com
Шилдт, Герберт.

Ш57

Java. Полное руководство, 10-е изд. : Пер.
2018. - 1488 с. : ил. - Парал. тит. англ.
ISBN 978-5-6040043-6-4 (рус.)

с англ. -СПб.

ООО "Альфа­

ББК

32.973.26-018.2.75

книга';

Все названия программных продуктов являются зарегистрированными торговыми марками соот­
ветствующих фирм.

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

McGraw-Hill Education.

Authorized translation from the English language edition
Copyright © 2018 Ьу McGгaw-Hill Education (PuЫisher).

puЬlished Ьу

McGraw-Hill Education,

All rights reserved. Except as peгmitted undeг the Copyгight Act of 1976, no рагt of this puЫication may
distributed in any form or Ьу any means, ог stoгed in а database ог гetrieval system, without
the ргiог wгitten peгmission of PuЬlisheг, with the exception that the progгam listings may Ье enteгed, stoгed,
and executed in а computer system, but they may not Ье гepгoduced fог puЬlication.
Ье repгoduced ог

Огасlе

and Java аге

гegisteгed trademaгks

of Огасlе

Coгpoгation and/oг

its affiliates.

Russian language edition puЫished Ьу Dialektika-Williams PuЫishing House according to the Agгeement
with R&l Enterpгises International, Copyright © 2018.
Научно-популярное издание
Герберт Шилдт

Java.

Полное руководство
10-е издание

Подписано в печать

15.05.2018. Формат 70х100/16
Times.
Усл. печ. л. 93,0. Уч.-изд. л. 81,3
Тираж 700 экз. Заказ № 3879
Гарнитура

Отпечатано в АО "Первая Образцовая типография"
Филиал "Чеховский Печатный Двор"

142300,

Московская область, г. Чехов, ул. Полиграфистов, д.

Сайт: www.chpd.гu,

ООО "Альфа-книга';

E-mail: sales@chpd.гu,

195027, Санкт-Петербург,

тел.

1
8 (499) 270-73-59

Магнитогорская ул" д.

30, лит.

А, пом.

848

ISBN 978-5-6040043-6-4

(рус.)

© 2018 Компьютерное издательство "Диалектика';

ISBN 978-1-259-58933-1

(анrл.)

© 2018 Ьу McGгaw-Hill Education (PuЬlisheг)

перевод, оформление, макетирование

Оглавление

Предисловие

Часть

1. Язык Java

Глава

1. История и развитие языка Java
2. Краткий обзор Java
Глава 3. Типы данных, переменные и массивы
Глава 4. Операции
Глава 5. Управляющие операторы
Глава 6. Введение в классы
Глава 7. Подробное рассмотрение классов и методов
Глава 8. Наследование
Глава 9. Пакеты и интерфейсы
Глава 10. Обработка исключений
Глава 11. Мноrопоточное проrраммирование
Глава 12. Перечисления, автоупаковка и аннотации
Глава 13. Ввод-вывод, оператор try с ресурсами и прочие вопросы
Глава 14. Обобщения
Глава 15. Лямбда-выражения
Глава 16. Модули
Глава

Часть

11. Библиотека Java

Глава

17. Обработка символьных строк
Глава 18. Пакет java. lang
Глава 19. Пакет java. util, часть 1. Collections Framework
Глава 20. Пакет java. util, часть 11. Прочие служебные классы
Глава 21. Пакет j ava. io для ввода-вывода
Глава 22. Система ввода-вывода NIO
Глава 23. Работа в сети
Глава 24. Обработка событий

29
33
35
57
79
109
131
163
185
221
249
279
303
337
379
413
459
493
527
529
559
633
727
795
851
889
911

б

Оглавление
Глава

25.

Введение в библиотеку

AWT: работа с окнами,

rрафикой и текстом

26.

Глава

Применение элементов управления, диспетчеров

компоновки и меню из библиотеки АWT
27. Изображения
Глава 28. Служебные средства параллелизма
Глава 29. Потоковый прикладной интерфейс API
Глава 30. Реrулярные выражения и друrие пакеты
Глава

Часть

11. Введение в проrраммирование ГПИ средствами Swing

Глава

31. Введение в библиотеку Swing
32. Исследование библиотеки Swing
Глава 33. Введение в меню Swing
Глава

Часть

111. Введение в проrраммирование ГПИ средствами JavaFX

Глава

34.
Глава 35.
Глава 36.
Часть

37.
38.

Глава

Часть

Введение в

JavaFX

Элементы управления
Введение в

JavaFX
меню JavaFX

IV. Применение Java

Глава

V.

947

Компоненты

Java Beans

Введение в сервлеты

Приnожения

979
1035
1063
1123
1153
1183
1185
1207
1239
1275
1277
1301
1355
1387
1389
1403
1429

Приложение А. Применение документирующих

комментариев в

Java
Приложение Б. Краткий обзор Java Web Start
Приложение В. Утилита JShell
Приложение Г. Утилита Аплеты
Предметный указатель

1431
1440
1451
1463
1472

Содержание

Предисловие

29

Книга для всех программистов
Структура книги
Исходный код примеров, доступный в Интернете

Особые благодарности
Дополнительная литература
От издательства

Часть

32

1. Язык Java

Глава

1. История

33
и развитие языка

Java

Происхождение Java
Зарождение современного программирования: язык С
Следующий этап: язык С++
Предпосылки к созданию Java
Создание языка Java
Связь с языком С#

Каким образом язык

Java повлиял на

Интернет

Аплеты на Java
Безопасность
Переносимость

Чудо

Java: байт-код

Выход за пределы аплетов
Сервлеты: серверные программы на
Терминология Java

Java

Простота

Объектная ориентированность
Надежность
Многопоточность
Архитектурная нейтральность
Интерпретируемость и высокая производительность
Распределенность
Динамичность

Эволюция языка Java
Версия Java SE 9
Культура нововведений

Глава

2.

30
30
31
31
31

Краткий обзор

36

37
39
39
42
42
42
43
43
44
45
46
46

47
47
48
48
49
49
49
49
50
54

55

Java

Объектно-ориентированное программирование
Две парадигмы

35
35

57
57
57

Содержание

8

Абстракция
Три принципа ООП
Первый пример простой программы
Ввод кода программы
Компиляция программы
Подробный анализ первого примера программы
Второй пример короткой программы
Два управляющих оператора

58
59
64
65
65
66

69

Условный оператор

71
71

Оператор цикла

73

if
for

Применение блоков кода

74

Вопросы лексики
Пробелы
Идентификаторы
Литералы
Комментарии
Разделители
Ключевые слова Java

75
76
76
76
76

Библиотеки классов

77

77
78

Java

Глава

3. Типы данных, переменные и
Java - строго типизированный язык

массивы

Примитивные типы
Целые числа
ТипЬуtе
Тип
Тип
Тип

short
int
long

Числа с плавающей точкой
Тип float
ТипdоuЫе

Символы
Логические значения

Подробнее о литералах.
Целочисленные литералы
Литералы с плавающей точкой
Логические литералы
Символьные литералы
Строковые литералы

Переменные
Объявление переменной
Динамическая инициализация
Область видимости и срок действия переменных
Преобразование и приведение типов
Автоматическое преобразование типов в Java
Приведение несовместимых типов
Автоматическое продвижение типов в выражениях
Правила продвижения типов
Массивы
Одномерные массивы
Многомерные массивы
Альтернативный синтаксис объявления массивов
Введение в символьные строки

79
79
79
80
81
81
81

82
82
83
83
84
85
86
87
88
89
89
90
90
91
91

92
95
95
95

97
98
99
99
102
106
106

Содержание

f лава 4.

Операции

Арифметические операции
Основные арифметические операции
Операция деления по модулю

Составные арифметические операции с присваиванием
Операции инкремента и декремента
Поразрядные операции
Поразрядные логические операции

Сдвиг влево
Сдвиг вправо
Беззнаковый сдвиг вправо
Поразрядные составные операции с присваиванием

Операции отношения
Логические операции
Укороченные логические операции

Операция присваивания
Тернарная операция ?
Предшествование операций

Применение круглых скобок

f лава 5. Управляющие операторы
Оператор

if

switch

Операторы цикла
Циклwhilе
Цикл
Цикл

do-while
for

Вложенные циклы

Операторы перехода
Применение оператора

Применение оператора
Оператор

fлава

6.

break
cont inue

return

Введение в классы

Основы классов

Общая форма класса
Простой класс
Объявление объектов
Подробное рассмотрение операции

new

Присваивание переменным ссылок на объекты
Введение в методы
Ввод метода в класс Вох

Возврат значений
Ввод метода, принимающего параметры

Конструкторы
Параметризированные конструкторы

Ключевое слово

thi s

Сокрытие переменных экземпляра

Сборка "мусора"
Класс

Stack

109
109
110
111
111
112
114
116
118
120
121
123
124
125
126
127
128
129
130
131
131
131
135
140
140
142
145
154
155
155
159
161

Операторы выбора
Условный оператор

9

163
163
163
164
167
168
169
170
171
173
174
177
179
180
180
181
181



Содержание
Глава

7.

Подробное рассмотрение классов и методов

185
185
188
191
193
195
196
199
202
204
205
207
210
212
213
216
218

Перегрузка методов
Перегрузка конструкторов

Применение объектов в качестве параметров
Подробное рассмотрение особенностей передачи аргументов

Возврат объектов
Рекурсия
Введение в управление доступом

Ключевое слово
Ключевое слово

s t аt i с
f inal

Еще раз о массивах
Вложенные и внутренние классы

Краткий обзор класса

St r ing

Применение аргументов командной строки

Аргументы переменной длины
Перегрузка методов с аргументами переменной длины
Аргументы переменной длины и неоднозначность

Глава

8. Наследование

Основы наследования
Доступ к членам класса и наследование
Практический пример наследования
Переменная из суперкласса может ссылаться на объект подкласса
Ключевое слово

super

Вызов конструкторов суперкласса с помощью ключевого слова
Другое применение ключевого слова

super

super

Создание многоуровневой иерархии
Порядок вызова конструкторов
Переопределение методов

Динамическая диспетчеризация методов
Назначение переопределенных методов
Применение переопределения методов

Применение абстрактных классов
Ключевое слово

f inal

в сочетании с наследованием

f inal
final

Предотвращение переопределения с помощью ключевого слова

Предотвращение наследования с помощью ключевого слова

Класс

Глава

9.

Obj ect
Пакеты и интерфейсы

Пакеты
Определение пакета
Поиск пакетов и переменная окружения
Краткий пример пакета
Доступ к пакетам и его компонентам
Пример доступа к пакетам

Импорт пакетов

Интерфейсы
Объявление интерфейса
Реализация интерфейсов
Вложенные интерфейсы

CLASSPATH

221
221
223
224
226
227
227
231
232
235
236
239
240
241
242
246
246
247
247
249
249
250
251
251
252
254
257
259
260
261
263

Содержание
Применение интерфейсов
Переменные в интерфейсах
Расширение интерфейсов
Методы с реализацией по умолчанию
Основы применения методов с реализацией по умолчанию
Прикладной пример

Вопросы множественного наследования

Применение статических методов в интерфейсе
Закрытые методы интерфейсов
Заключительные соображения по поводу пакетов и интерфейсов

Глава

10. Обработка исключений

Основы обработки исключений
Типы исключений
Необрабатываемые исключения
Применение блоков операторов

try

и

catch

Вывод описания исключения
Применение нескольких операторов
Вложенные операторы t ry
Оператор throw
Оператор throws

catch

Оператор finally
Встроенные в Java исключения

Создание собственных подклассов исключений
Цепочки исключений

Дополнительные средства для обработки исключений
Применение исключений

Глава

11. Многопоточное программирование
Java

Модель потоков исполнения в
Приоритеты потоков
Синхронизация

Обмен сообщениями
Класс Thread и интерфейс RunnaЫe
Главный поток исполнения

Создание потока исполнения
Реализация интерфейса RunnaЫe
Расширение класса Thread
Выбор способа создания потоков исполнения
Создание многих потоков исполнения
Применение методов isAlive () и join ()
Приоритеты потоков исполнения
Синхронизация
Применение синхронизированных методов
Оператор synchronized
Взаимодействие потоков исполнения
Взаимная блокировка

Приостановка, возобновление и остановка потоков исполнения
Получение состояния потока исполнения

Одновременное создание и запуск потоков исполнения
фабричными методами
Применение многопоточности

11
264
268
270
271
272
274
275
276
277
278
279
279
280
281
282
284
284
286
289
290
291
293
295
298
299
301
303
304
305
306
307
307
308
310
310
312
313
314
315
318
319
319
322
323
328
330
333
335
336

Содержание

12
Глава

12. Перечисления,

автоупаковка и аннотации

Перечисления
Основные положения о перечислениях
Методы values () и valueOf ()
Перечисления в Java относятся к типам классов
Перечисления наследуются от класса Enum
Еще один пример перечисления

Оболочки типов
Класс
Класс

Character
Boolean

Оболочки числовых типов

Автоупаковка
Автоупаковка и методы
Автоупаковка и автораспаковка в выражениях

Автоупаковка и распаковка значений из классов Boolean и Character
Автоупаковка и автораспаковка помогает предотвратить ошибки
Предупреждение
Аннотации
Основы аннотирования программ
Правила удержания аннотаций

Получение аннотаций во время выполнения с помощью рефлексии
Второй пример применения рефлексии
Получение всех аннотаций
Интерфейс AnnotatedElement
Использование значений по умолчанию

Маркерные аннотации
Одночленные аннотации

Встроенные аннотации
Типовые аннотации
Повторяющиеся аннотации
Некоторые ограничения на аннотации

Глава

13. Ввод-вывод, оператор try с ресурсами

и прочие вопросы

Основы ввода-вывода
Потоки ввода-вывода
Потоки ввода-вывода байтов и символов
Предопределенные потоки ввода-вывода

Чтение данных, вводимых с консоли
Чтение символов

Чтение символьных строк

Запись данных, выводимых на консоль
Класс

PrintWriter

Чтение и запись данных в файлы
Автоматическое закрытие файла
Модификаторы доступа transient и
Применение операции

volati le

instanceof
s t r i сt f р

Модификатор доступа
Платформенно-ориентированные методы
Применение ключевого слова

assert

Параметры включения и отключения режима проверки утверждений

337
337
338
340
341
343
346
347
348
348
349
350
351
352
354
355
356
356
357
358
358
361
362
364
364
366
367
368
371
376
378
379
379
380
380
382
383
384
385
386
387
388
395
399
399
402
402
403
406

Содержание

Статический импорт
Вызов перегружаемых конструкторов по ссылке
Компактные профили Java API

Глава

this ()

14. Обобщения

Что такое обобщения
Простой пример обобщения
Обобщения оперируют только ссылочными типами
Обобщенные типы различаются по аргументам типа
Каким образом обобщения повышают типовую безопасность

Обобщенный класс с двумя параметрами типа
Общая форма обобщенного класса
Ограниченные типы
Применение метасимвольных аргументов
Ограниченные метасимвольные аргументы
Создание обобщенного метода
Обобщенные конструкторы
Обобщенные интерфейсы
Базовые типы и унаследованный код
Иерархии обобщенных классов
Применение обобщенного суперкласса
Обобщенный подкласс
Сравнение типов в обобщенной иерархии во время выполнения
Приведение типов

Переопределение методов в обобщенном классе

Выведение типов и обобщения
Стирание
Мостовые методы

Ошибки неоднозначности
Некоторые ограничения, присущие обобщениям
Получить экземпляр по параметру типа нельзя

Ограничения на статические члены
Ограничения на обобщенные массивы
Ограничения на обобщенные исключения

Глава

15. Лямбда-выражения

Введение в лямбда-выражения
Основные положения о лямбда-выражениях
Функциональные интерфейсы
Некоторые примеры лямбда-выражений
Блочные лямбда-выражения
Обобщенные функциональные интерфейсы

Передача лямбда-выражений в качестве аргументов

Лямбда-выражения и исключения
Лямбда-выражения и захват переменных
Ссылки на методы
Ссылки на статические методы
Ссылки на методы экземпляра
Ссылки на обобщенные методы
Ссылки на конструкторы
Предопределенные функциональные интерфейсы

13
406
409
411

413
414
414
418
419
419
421
423
423
426
429
434
436
437
439
442
442
444
446

449
449
450
451
452
454
455
456
456
456
458
459
459
460
461
463
466
468

470
473
475
476
476
478
482
485

490

Содержание

14
Глава

16. Модули

Основные положения о модулях
Простой пример модуля
Компиляция и выполнение первого примера модульного приложения
Подробное рассмотрение операторов requires и exports

Модуль j ava. base и платформенные модули
Унаследованный код и безымянные модули
Экспорт в конкретный модуль
Применение оператора

r equ i r е s t r an s i t i v е

Применение служб
Основные положения о службах и поставщиках их услуг
Ключевые слова для помержки служб
Пример модульной службы

Графы модулей
Специальные средства модулей
Открытые модули
Оператор

opens
requires static
j 1 ink и модульные архивные

Оператор

Утилита
JАR-файлы
Связывание файлов в развернутом каталоге
Связывание модульных архивных JАR-файлов
Файлы формата JMOD
Об уровнях и автоматических модулях
Заключительные соображения по поводу модулей

Часть

11. Библиотека Java

Глава

527

17. Обработка символьных строк

Конструкторы символьных строк
Длина символьной строки

Специальные строковые операции
Строковые литералы
Сцепление строк
Сцепление символьных строк с другими типами данных
Преобразование символьных строк и метод toString ()
Извлечение символов
Метод charAt ()
Метод getChars ()
Метод
Метод

getBytes ()
toCharArray ()

Сравнение символьных строк
Методы equals () и equalsignoreCase
Метод regionМatches ()
Методы startsWith () и endsWith ()
Метод
Метод

()

equals () в сравнении с операцией==
cornpareTo ( )

Поиск в символьных строках
Видоизменение символьных строк
Метод substring ()
Метод concat ()
Метод replace ()
Метод t r irn ( )

493
493
494
499
500
502
503
504
505
510
511
512
512
519
520
520
521
521
522
522
523
524
524
525

529
530
532
532
533
533
534
534
536
536
536
537
537
537
538
539
539
540
540
542
544
544
545
545
546

Содержание
Преобразование данных методом
Смена регистра букв в строке

v а 1 u еО f ( )

Соединение символьных строк
Дополнительные методы из класса

String
StringBuffer
Методы length ( ) и сарае i ty ( )
Метод ensureCapac i ty ( )
Метод setLength ()
Методы charAt () и setCharAt ()
Метод getChars ()
Метод append ( )
Метод insert ()
Метод reverse ( )
Методы delete () и deleteCharAt ()
Метод replace ()
Метод substring ()
Дополнительные методы из класса StringBuffer
Класс StringBuilder

Класс

Глава

18. Пакет java. lang

Оболочки примитивных типов
Класс Number
Классы DouЫe и Float
Meтoдыisinfinite() иisNaN()
Классы Byte, Short, Integer и Long
Класс Character
Дополнения класса
Класс Boolean

Character для поддержки кодовых точек в Юникоде

Класс
Класс

Void
Process
Класс Run t ime
Управление памятью

Выполнение других программ
Класс

Runtime. Version

Класс ProcessBuilder
Класс System
Измерение времени выполнения программы
методом

currentTimeMills ()
arraycopy ( )

Применение метода

Свойства окружения

Интерфейс System. Logger и класс System. LoggerFinder
Класс Obj ect
Применение метода clone () и интерфейса CloneaЫe
Класс Class
Класс ClassLoader
Класс Ма t h
Тригонометрические функции
Экспоненциальные функции
Функции округления
Прочие методы из класса Ма th

Класс
Класс

StrictMath
Compiler

15
546
547
548
549
550
551
552
552
552
553
554
554
555
555
556
557
557
558
559
560
560
560
565
565
578

581
583
584
584
586
588
589
590
591
594
596
597
598
599
599
600
602
605
606
606
607
607
609
612

612

Содержание

16

Классы Thread, ThreadGroup и интерфейс RunnaЫe
Интерфейс RunnaЫe
Класс

Thread
Класс ThreadGroup
Классы ThreadLocal и Inheri taЬleThreadLocal
Класс Package
Класс Module
Класс ModuleLayer
Класс RuntimePermission
Класс ThrowaЫe
Класс
Класс

SecurityManager
StackTraceElement
Класс StackWalker и интерфейс StackWalker. StackFrame
Класс Enum
Глава

19. Пакет java. util, часть 1. Collections Framework

Краткий обзор коллекций
Интерфейсы коллекций
Интерфейс

Collection

Интерфейс List
Интерфейс Set
Интерфейс SortedSet
Интерфейс NavigaЬleSet
Интерфейс Queue
Интерфейс Dequeue
Классы коллекций
Класс

ArrayList
LinkedList
Класс HashSet
Класс LinkedHashSet
Класс TreeSet
Класс PriorityQueue
Класс ArrayDeque
Класс EnumSet
Класс

Доступ к коллекциям через итератор
Применение интерфейса Iterator
Цикл for в стиле for each как альтернатива итераторам
Итераторы-разделители

Сохранение объектов пользовательских классов в коллекциях
Интерфейс RandomAccess
Манипулирование отображениями
Интерфейсы отображений
Классы отображений
Компараторы
Применение компараторов
Алгоритмы коллекций

Массивы
Унаследованные классы и интерфейсы
Интерфейс Enumeration
Класс Vector
Класс

Класс

Stack
Dictionary

613
613

613
616

621
621
623
624
624
624
624
624
626
626
633
634
636
637
640

642
643
644
646

647
649
650
654
656
657
658
659
660
661

662
664
665
666
670
672
672
672
680
686

689
695
702
708
709
709
714
716

Содержание
Класс HashtaЫe
Класс

717
720
724
726

Properties

Применение методов

store ()

и

load ()

Заключительные соображения по поводу коллекций

Глава

20. Пакет java. util, часть 11. Прочие служебные классы

Класс

StringTokenizer
Класс Bi tSet
Классы Optional, OptionalDouЬle, Optionalint
Класс Date
Класс Calendar
Класс GregorianCalendar
Класс TimeZone
Класс SimpleTimeZone
Класс Locale
Класс Random
Классы Timer и TimerTask
Класс Currency
Класс Formatter
Конструкторы класса Forrna t t er
Методы из класса Forrna t t er

и

OptionalLong

Основы форматирования
Форматирование строк и символов
Форматирование чисел
Форматирование времени и даты
Спецификаторы формата %n и%%
Указание минимальной ширины поля
Указание точности

Применение признаков формата
Выравнивание выводимых данных
Признаки пробела, +, О и (
Признак запятой
Признак#

Прописные формы спецификаторов формата
Применение индекса аргумента

Закрытие объекта типа

Аналог функции

Forrnat ter
pr int f () в Java

Класс Scanner
Конструкторы класса Scanner
Основы сканирования
Некоторые примеры применения класса
Установка разделителей

17

Scanner

Прочие средства класса

Scanner
ResourceBundle, ListResourceBundle
PropertyResourceBundle

727
727
729
733
736
738
742
743
745
746
747
750
753
754
754
755
756
758
758
760
761
762
763
764
765
765
766
767
767
768
769
770
770
770
772
775
779
781

Классы
и

Прочие служебные классы и интерфейсы
Подпакеты, входящие в состав пакета

j ava. util
java. util. concurrent, j ava. util. concurrent.
atornic,java.util.concurrent.locks
Пакет j ava. ut i l. funct ion
Пакет java. util. j ar

782
787
788

Пакеты

789
789
792

Содержание

18

Пaкeтjava.util.logging
Пaкeтjava.util.prefs
Пакет

java.util.regex

Пaкeтjava.util.spi
Пакет

java. util. stream

Пaкeтjava.util.zip

Глава

21. Пакет j ava. io для ввода-вывода

793
793
793
793
793
793

Исключения ввода-вывода

795
796
796
800
801
802
803
803
804

Два способа закрытия потоков ввода-вывода

804

Классы потоков ввода-вывода

806
807
807
808
809

Классы и интерфейсы ввода-вывода
Класс File
Каталоги
Применение интерфейса
Альтернативный метод
Создание каталогов

F i l enameF i l t er
1istFi1 е s ( )

Интерфейсы AutoCloseaЫe, CloseaЫe и FlushaЫe

Потоки ввода-вывода байтов
Класс

InputStream
OutputStream
Класс FileinputStream
Класс FileOutputStream
Класс ByteArrayinputStream
Класс ByteArrayOutputStream
Класс

Фильтруемые потоки ввода-вывода байтов
Буферизованные потоки ввода-вывода байтов

SequenceinputStream
Класс PrintStream
Классы DataOutputStream и DatainputStream
Класс RandomAccessFile
Класс

Потоки ввода-вывода символов
Класс

Reader
Writer
FileReader
FileWriter
Класс CharArrayReader
Класс CharArrayWriter
Класс BufferedReader
Класс BufferedWriter
Класс PushbackReader
Класс PrintWriter
Класс Console
Класс
Класс
Класс

Сериализация
Интерфейс SerializaЫe
Интерфейс ExternalizaЫe
Интерфейс

Obj ectOutput

811
813

815
817

817
821
823
826
828
829
829
830
831
832
833
834
836
837
838
839
840

842
843
843

KлaccObjectOutputStream

844
844

Интерфейс

845

Obj ectinput

KлкcObjectinputStream

846

Пример сериализации

848
849

Преимущества потоков ввода-вывода

Содержание

Глава

22.

Система ввода-вывода

NIO

Классы системы ввода-вывода NIO
Основные положения о системе ввода-вывода
Буферы
Каналы
Наборы символов и селекторы
Усовершенствования в системе NI0.2
Интерфейс Path
Класс Files
Класс Paths
Интерфейсы атрибутов файлов
Классы

FileSystem, FileSystems

и

NIO

FileStore

Применение системы ввода-вывода NIO
Применение системы NIO для канального ввода-вывода
Применение системы NIO для потокового ввода-вывода
Применение системы ввода-вывода NIO для операций
в файловой системе

Глава

23.

Работа в сети

Основы работы в сети
Сетевые классы и интерфейсы
Класс InetAddress
Фабричные методы
Методы экземпляра
Классы Inet4Address и Inet6Address
Клиентские сокеты по протоколу TCP/IP
Класс URL
Класс
Класс
Класс

URLConnection
Ht tpURLConnection
URI

Сооkiе-файлы
Серверные сокеты по протоколу

TCP/IP

Дейтаграммы
Класс DatagramSocket
Класс DatagramPacket

Глава

24. Обработка событий

Два подхода к обработке событий
Модель делегирования событий
События
Источники событий
Приемники событий
Классы событий
Класс

Act ionEvent
AdjustmentEvent
Класс ComponentEvent
Класс ContainerEvent
Класс FocusEvent
Класс ItemEvent
Класс KeyEvent
Класс MouseEvent
Класс MouseWheelEvent
Класс

19
851
851
852
852
855
856
856
857
858
861
862
864
864
865
876
879
889
889
891
891
892
893
894
894
898
900
903
905
905
905
906
907
908
911
912
912
912
913
914
914
916
916
917
918
919
921
922
923
924

Содержание

20

Класс
Класс

TextEvent
WindowEvent

Источники событий
Интерфейсы приемников событий
Интерфейс ActionListener
Интерфейс AdjustmentListener
Интерфейс ComponentListener
Интерфейс ContainerListener
Интерфейс FocusListener
Интерфейс ItemListener
Интерфейс KeyListener
Интерфейс MouseListener
Интерфейс MouseMot ionListener
Интерфейс MouseWheelListener
Интерфейс TextListener
Интерфейс WindowFocusListener
Интерфейс WindowListener

Применение модели делегирования событий
Основные принципы обработки событий в ГПИ средствами АWT
Обработка событий от мыши
Обработка событий от клавиатуры
Классы адаптеров
Внутренние классы
Анонимные внутренние классы

Глава

25.

Введение в библиотеку AWT: работа с окнами,
графикой и текстом

Классы библиотеки АWT
Основные положения об окнах
Класс

Класс
Класс
Класс
Класс
Класс

Component
Container
Panel
Window
Frame
Canvas

Работа с обрамляющими окнами
Установка размеров окна

Сокрытие и отображение окна
Установка заголовка окна

Закрытие обрамляющего окна
Meтoдpaint

()

Отображение символьной строки
Установка цвета переднего и заднего плана
Запрос на повторное воспроизведение
Создание прикладной программы на основе класса

Поддержка графики
Рисование линий
Рисование прямоугольников

Рисование эллипсов и окружностей

Рисование дуг
Рисование многоугольников
Демонстрация методов рисования

Изменение размеров графики

Frame

925
926
927
928
929
929
929
929
929
930
930
930
930
931
931
931
931
931
932
933
937
940

943
945
947
948
950
951
951
952
952
952
952
952
953
953
953
953
954
954
955
955
957
957
958
958
959
959
959
960
962

Содержание
Работа с цветом
Методы из класса

Color

Установка текущего цвета графики
Пример программы, демонстрирующий работу с цветом
Установка режима рисования

Работа со шрифтами
Определение доступных шрифтов
Создание и выбор шрифта
Получение сведений о шрифте

Управление форматированием выводимого текста
Глава

26. Применение элементов управления, диспетчеров
компоновки и меню из библиотеки AWT

Основные положения об элементах управления
Ввод и удаление элементов управления
Реагирование на элементы управления

Исключение типа

HeadlessExcept ion

Метки
Экранные кнопки
Обработка событий от кнопок

Флажки
Обработка событий от флажков
Кнопки-переключатели

Элементы управления выбором
Обработка событий от раскрывающихся списков
Использование списков
Обработка событий от списков
Управление полосами прокрутки
Обработка событий от полос прокрутки
Текстовые поля
Обработка событий в текстовых полях

Текстовые области
Диспетчеры компоновки
Класс FlowLayout
Класс

BorderLayout

Вставки
Класс

GridLayout
CardLayout
Класс GridBagLayout
Класс

Меню и строки меню
Диалоговые окна

О переопределении метода

Глава

paint ()

27. Изображения

Форматы файлов изображений
Основы работы с изображениями: создание, загрузка и отображение
Создание объекта класса Image
Загрузка изображения
Воспроизведение изображения

Двойная буферизация

21
963
964
965
965
966
968
970
971
974
975
979
980
980
981
981
981
983
984
988
989
991
992
993
995
997
999
1000
1002
1003
1005
1007
1008
1010
1011
1013
1015
1018
1023
1029
1033
1035
1035
1036
1036
1037
1037
1039

Содержание

22

Интерфейс

ImageProducer
MemoryimageSource
Интерфейс ImageConsumer
Класс PixelGrabber
Класс ImageFilter
Фильтр класса CropimageFilter
Фильтр класса RGBimageFi lter
Класс

Дополнительные классы для формирования изображений
Глава

28. Служебные средства параллелизма

Пакеты параллельного прикладного интерфейса
Пакет
Пакет

API

j ava. util. concurrent. atomic
j ava. util. concurrent. locks

Применение объектов синхронизации
Класс

Semaphore
CountDownLatch
Класс CyclicBarrier
Класс Exchanger
Класс Phaser
Класс

Применение исполнителя
Простой пример исполнителя
Применение интерфейсов CallaЫe и

Future

Перечисление TimeUni t
Параллельные коллекции
Блокировки
Атомарные операции

Параллельное программирование средствами Foгk/Join Fгamework
Основные классы Fork!Join Framework
Стратегия "разделяй и властвуй"
Первый простой пример вилочного соединения

Влияние уровня параллелизма
Пример применения класса Recursi veTask
Асинхронное выполнение задач
Отмена задачи
Определение состояния завершения задачи
Перезапуск задачи
Предмет дальнейшего изучения
Рекомендации относительно вилочного соединения

Служебные средства параллелизма в сравнении с традиционным
подходом к многозадачности в Java

Глава

29.

Потоковый прикладной интерфейс

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

Операции сведения
Параллельные потоки данных

Отображение
Накопление
Итераторы и потоки данных
Применение итератора в потоке данных

API

1042
1042
1044
1045
1048
1048
1050
1062
1063
1064
1066
1066
1066
1067
1073
1075
1078
1080
1088
1089
1091
1094
1095
1096
1099
1101
1102
1106
1107
1110
1114
1117
1117
1118
1118
1118
1120
1121
1123
1123
1124
1127
1128
1132
1135
1138
1143
1147
1147

Содержание
Применение итератора-разделителя

Дальнейшее изучение потокового прикладного интерфейса
Глава

1149
1152

API

30. Реrулярные выражения и друrие пакеты

Обработка регулярных выражений
Класс
Класс

Pattern
Matcher

Синтаксис регулярных выражений

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

Рефлексия
Удаленный вызов методов
Простое приложение "клиент-сервер'; использующее механизм
Форматирование даты и времени средствами пакета
Класс
Класс

Пакеты из прикладного интерфейса

API даты и времени

Основные классы даты и времени
Форматирование даты и времени
Синтаксический анализ символьных строк даты и времени
Дальнейшее изучение пакета

Часть

j

аv а

RMI

j ava. text

DateFormat
SimpledateFormat

. t ime

23

1153
1153
1154
1154
1155
1156
1162
1163
1163
1167
1168
1171
1172
1174
1176
1177
1178
1181
1182

111. Введение в программирование ГПИ средствами Swing 1183

Глава

31. Введение в библиотеку Swing

Происхождение библиотеки Swing
Построение библиотеки Swing на основе библиотеки АWT

Главные особенности библиотеки
Легковесные компоненты

Swing

Swing

Подключаемый стиль оформления
Связь с архитектурой

MVC

Компоненты и контейнеры
Компоненты
Контейнеры
Панели контейнеров верхнего уровня

Пакеты библиотеки

Swing

Простое Swing-приложение

Обработка событий
Рисование средствами Swing
Основы рисования
Вычисление области рисования
Пример рисования

Глава

32. Исследование

Классы

библиотеки

JLabel и Imageicon
JTextField
Кнопки из библиотеки Swing
Класс JButton
Класс JToggleButton
Класс

Swing

1185
1185
1186
1186
1187
1187
1188
1189
1189
1190
1190
1191
1192
1196
1200
1200
1202
1203
1207
1207
1209
1211
1212
1214

24

Содержание

1217
1218
1221
1223
1225
1229
1232
1236

Флажки

Кнопки-переключатели
Класс

JTabbedPane
JScrollPane
Класс JList
Класс JComboBox
Класс

Деревья
Класс

Глава

JT аЫ е

33.

Введение в меню

Swing

Основные положения о меню

Краткий обзор классов

JMenuBar, JMenu

и

JMenuitem

Класс

JMenuBar
Класс JMenu
Класс JMenuitem
Создание главного меню

Ввод мнемоники и оперативных клавиш в меню
Ввод изображений и всплывающих подсказок в пункты меню
Классы JRadioBut tonMenuitem и JCheckBoxMenuitem
Создание всплывающего меню
Создание панели инструментов
Действия
Составление окончательного варианта программы MenuDemo
Дальнейшее изучение библиотеки Swing

Часть

IV. Введение в программирование ГПИ средствами JavaFX

Глава

34. Введение в JavaFX

Основные понятия JavaFX
Пакеты JavaFX
Классы подмостков и сцены
Узлы и графы сцены
Компоновки
Класс приложения и методы
Запуск JаvаFХ-приложения

ero жизненного цикла

Скелет JаvаFХ-приложения
Компиляция и выполнение JаvаFХ-приложения
Поток исполнения приложения
Метка - простейший элемент управления в JavaFX
Применение кнопок и событий
Основы обработки событий в JavaFX
Элемент управления экранной кнопкой
Демонстрация обработки событий на примере экранных кнопок
Рисование непосредственно на холсте

Глава

35.

Элементы управления

JavaFX

Классы Image и ImageView
Ввод изображения в метку
Ввод изображения в экранную кнопку
Класс

ToggleButton

Класс RadioButton
Обработка событий изменения в группе кнопок-переключателей
Другой способ управления кнопками-переключателями

1239
1239
1241
1241
1243
1244
1245
1249
1251
1253
1255
1259
1262
1268
1274
1275
1277
1278
1278
1279
1279
1279
1280
1280
1281
1285
1286
1286
1288
1289
1290
1291
1294
1301
1301
1304
1306
1309
1312
1316
1317

Содержание
Класс

1320
1325
1329

CheckBox

Класс ListView
Представление списка с полосами прокрутки

Активизация режима одновременною выбора нескольких
элементов из списка
Класс

ComboBox
Класс TextField
Класс ScrollPane
Класс TreeView
Эффекты и преобразования
Эффекты

Преобразования
Демонстрация эффектов и преобразований
Ввод всплывающих подсказок
Отключение элементов управления

f лава 36. Введение в меню JavaFX
Основные положения о меню

Краткий обзор классов
Класс MenuBar
Класс
Класс

MenuBar, Menu

и

Menuitem

Menu
Menuitem

Создание главного меню
Ввод мнемоники и оперативных клавиш в меню

Ввод изображений в пункты меню
Классы

RadioMenuitem и CheckMenuitem

Создание контекстного меню
Создание панели инструментов
Составление окончательного варианта приложения

Дальнейшее изучение

Часть

MenuDemo

JavaFX

V. Применение Java

fлава

Общее представление о компонентах

Java Beans

Преимущества компонентов Java Beans
Самоанализ
Проектные шаблоны для свойств компонентов
Проектные шаблоны для событий
Методы и проектные шаблоны
Применение интерфейса Beaninfo
Привязанные и ограниченные свойства

Java Beans

Настройщики

Прикладной интерфейс

Java Beans API
Introspector
Класс PropertyDescriptor
Класс EventSetDescriptor
Класс MethodDescriptor
Пример компонента Java Bean
Класс

1330
1331
1335
1338
1342
1347
1348
1349
1350
1354
1354
1355
1355
1357
1357
1358
1359
1360
1366
1368
1369
1372
1375
1378
1385
1387

37. Компоненты Java Beans

Сохраняемость компонентов

25

Java Beans

1389
1389
1390
1390
1391
1392
1393
1393
1394
1394
1395
1395
1398
1398
1398
1398
1398

Содержание

26
Глава

38. Введение в

сервлеты

Предпосылки для разработки сервлетов
Жизненный цикл сервлета
Варианты разработки сервлетов
Применение контейнера сервлетов
Простой пример сервлета

Tomcat

Создание и компиляция исходного кода сервлета
Запуск контейнера сервлетов Tomcat на выполнение

Запуск веб-браузера и запрос сервлета
Прикладной интерфейс Servlet API
Пакет j avax. servlet
Интерфейс Servlet
Интерфейс ServletConfig
Интерфейс ServletContext
Интерфейс ServletRequest
Интерфейс ServletResponse
Класс

GenericServlet
ServletinputStrearn
Класс ServletOutputStrearn
Класс ServletException

Класс

Ввод параметров сервлета
Пакет j avax. servlet. http
Интерфейс HttpServletRequest
Интерфейс HttpServletResponse
Интерфейс HttpSession
Класс
Класс

Cookie
HttpServlet

Обработка НТТР-запросов и ответов
Обработка НТТР-запросов типа
Обработка НТТР-запросов типа
Применение сооkiе-файлов
Отслеживание сеансов связи

Часть

VI.

GET
POST

Приложения

1403
1403
1404
1405
1406
1407
1408
1409
1409
1409
1410
1410
1411
1411
1412
1413
1413
1414
1414
1414
1414
1416
1417
1418
1419
1419
1421
1422
1422
1424
1425
1427
1429

Приложение А. Применение документирующих
комментариев в
Дескрипторы утилиты j avadoc
Дескриптор @author
Дескриптор { @code}
Дескриптор @deprecated
Дескриптор { @docRoot}
Дескриптор @except ion
Дескриптор @hidden
Дескриптор { @index}
Дескриптор {@inheri tDoc}
Дескриптор { @1 ink}
Дескриптор {@linkplain}
Дескриптор
Дескриптор
Дескриптор

Дескриптор

{@li teral}
@pararn
@provides
@return

Java

1431
1431
1432
1433
1433
1433
1433
1433
1434
1434
1434
1434
1434
1435
1435
1435

Содержание
Дескриптор
Дескриптор
Дескриптор
Дескриптор
Дескриптор
Дескриптор
Дескриптор
Дескриптор
Дескриптор

1435
1436
1436
1436
1436
1436
1436
1437
1437
1437
1437
1438

@see
@serial
@serialData
@serialField
@since
@throws
@uses
{@value}
@version

Общая форма документирующих комментариев
Результаты, выводимые утилитой

j avadoc

Пример применения документирующих комментариев

Приложение Б. Краткий обзор

Java Web Start

Назначение Java Web Start
Главные элементы Java Web Start
Упаковка приложений Java Web Start в архивный JАR-файл
Подписание приложений Java Web Start
Запуск приложений Java Web Start с помощью JNLР-файла
Связывание приложения Java Web Start с JNLР-файлом

Экспериментирование с

Java Web Start в локальной файловой

системе

Создание архивного JАR-файла для приложения Togg 1 eBu t t onDerno
Создание хранилища ключей и подписание архивного JАR-файла
Создание JNLР-файла для запуска приложения Togg 1 eBu t t onDerno
Создание краткого НТМL-файла StartTBD. html
Ввод JNLР-файла в список Exception Site Ust на панели управления Java
Выполнение приложения ToggleBut tonDerno из браузера

Выполнение приложений Java Web Start с помощью утилиты j
Выполнение аплетов средствами Java Web Start

Приложение В. Утилита

JShell

Основные положения об утилите

JShell

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

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

Применение интерфейса
Вычисление выражений и встроенных переменных
Импорт пакетов
Исключения

Другие команды JShell
Дальнейшее изучение JShell
Приложение

f.

Аплеты

Два типа аплетов

Основы разработки аплетов
Класс

Applet

Архитектура аплетов
Скелет аплета

Инициализация и прекращение работы аплета

Аплеты на основе библиотеки
Предметный указатель

Swing

27

avaws

1440
1440
1441
1441
1442
1443
1444
1445
1446
1447
1448
1449
1449
1450
1450
1450
1451
1451
1454
1455
1456
1457
1458
1459
1460
1460
1461
1463
1463
1464
1465
1465
1466
1468
1469
1472

Об авторе
Герберт Шилдт является автором многочисленных книг по программирова­

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

Java.

Его книги продаются милли­

онными тиражами и переведены на многие языки мира. Его перу принадлежит не­

мало книг по

Java, в том числе Iпtrodиcing JavaFX 8 Prograтming, Java: руководство
для начинающих, Java: методики программирования Шилдта, SWING: руковод­
ство для начинающих, Искусство программирования на Java, а также настоящее
издание. Он написал немало книг и по другим языкам программирования, включая
С, С++ и С#. Интересуясь всеми аспектами вычислительной техники, Герберт уделя­

ет основное внимание языкам программирования. Герберт окончил Иллинойский
университет, получив обе степени

-

бакалавра и магистра. Подробнее об авторе

можно узнать, посетив его веб-сайт по адресу

www. HerbSchi ldt. com.

О научном редакторе
Д-р Дэнни Ковард редактировал все издания этой книги. Он ввел понятие серв­

летов

Java

Java в

первую версию платформы

Java ЕЕ, внедрил веб-службы на платформе
Java SE 7. Он так­

МЕ, составил общую стратегию и план разработки версии

же заложил основы технологии
ное дополнение к стандарту

Java WebSocket API.

JavaFX, а совсем недавно разработал самое круп­
Java ЕЕ 7 и прикладному программному интерфейсу

Д-р Ковард обладает необычайно обширными знаниями всех

аспектов технологии

Java:

от программирования на

ных программных интерфейсов

API

Java

до разработки приклад­

вместе с опытными специалистами вданной

области, а также многолетним опытом работы в исполнительном комитете

Java
Community Process. Он также является автором книг Java WebSocket Prograттiпg
и Java ЕЕ: The Big Pictиre. Д-р Ковард окончил Оксфордский университет, получив
степени бакалавра, магистра и доктора математических наук.

Предисловие

Java -

один из самых важных и широко применяемых языков программиро­

вания в мире на протяжении многих лет. В отличие от некоторых других языков

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

Java не только

не уменьшилось со временем, а, наобо­

рот, возросло. С момента первого выпуска он выдвинулся на передний край про­
граммирования приложений для Интернета. И каждая последующая версия лишь
укрепляла эту позицию. Ныне

Java по-прежнему остается первым

и самым лучшим

языком для разработки веб-ориентированных приложений. Проще говоря, боль­

шая часть современного кода написана на
значении языка

Java для

Java.

И это свидетельствует об особом

программирования.

Основная причина успеха

Java -

его гибкость. Начиная с первой версии

1.0, этот

язык непрерывно адаптируется к изменениям в среде программирования и подхо­

дам к написанию программ. А самое главное

-

он не просто следует тенденциям

в программировании, а помогает их создавать. Способность

Java

адаптировать­

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

Со времени публикации первого издания этой книги в

1996 году она

претерпе­

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

Java.
Java SE 9 (JDK 9). А это означает,
поскольку в версии Java SE 9 появился

Настоящее, десятое, издание обновлено по версии
что оно содержит немало нового материала,

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

Java,

поскольку они внес­

ли в его синтаксис не только новый элемент, но и десять новых ключевых слов.

Модули оказали заметное влияние и на библиотеку

Java API,

так как вместе с ними

появились новые инструментальные средства, а существовавшие до этого сред­

ства были обновлены. Кроме того, был определен новый формат файлов. В силу
особого значения модулей в настоящем издании им посвящена отдельная глава
Помимо модулей, в версии

JDK 9

16.

предоставляется ряд других новых средств.

Наибольший интерес среди них представляет утилита

JShell,

предоставляющая

интерактивную среду, в которой удобно экспериментировать с фрагментами кода,
не прибегая непосредственно к написанию целой программы. Эта утилита при-

Предисловие

30

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

JShell

представлено в приложении В к настоящему изданию книги. Как и в предыдущих

выпусках, в

JDK 9 сделан

целый ряд менее значительных обновлений и усовершен­

ствований как самого языка

Java,

так и библиотек

Java API.

Поэтому в настоящем

издании обновлен материал практически всех глав книги. И, наконец, следует за­

метить, что в версии

Java SE 9 больше не рекомендуются к употреблению аплеты
API. Поэтому они не рассматриваются в основном тек­

и их прикладной интерфейс

сте настоящего издания книги, хотя краткое введение в аплеты приведено в при­

ложении Г.

Книга для всех программистов
Эта книга предназначена для всех категорий программистов: от начинающих

до опытных. Начинающий программист найдет в ней подробные пошаговые опи­
сания и немало полезных примеров написания кода на

рение более сложных функций и библиотек

Java, а углубленное рассмот­
Java должно привлечь внимание опыт­

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

Структура книги
Эта книга служит исчерпывающим справочным пособием по языку

Java, в

кото­

ром описываются его синтаксис, ключевые слова и основополагающие принципы

программирования. В ней рассматривается также значительная часть библиотеки

Java API.

Книга разделена на пять частей, каждая из которых посвящена отдельно­

му аспекту среды программирования

Java, а в дополнительной

шестой части книги

приведены приложения к ней.

В части

I представлено

подробное учебное пособие по языку

Java.

Она начина­

ется с рассмотрения таких основных понятий, как типы данных, операции, управ­

ляющие операторы и классы. Затем описываются правила наследования, пакеты,

интерфейсы, обработка исключений и многопоточная обработка. Далее рассма­
триваются аннотации, перечисления, автоупаковка, обобщения, лямбда-выраже­
ния и операции ввода-вывода. А заключительная глава этой части посвящена мо­
дулям, которые, как упоминалось ранее, являются самым важным нововведением

в версии

Java SE 9.
II описываются

В части

API.

основные компоненты стандартной библиотеки

Java

В ней обсуждаются следующие вопросы: символьные строки, операции вво­

да-вывода, работа в сети, стандартные утилиты, каркас коллекций

Framework),

(Collections

библиотека АWT, обработка событий, формирование изображений,

параллельная обработка, включая каркас

Fork/Join Framework,

регулярные выра­

жения и библиотека потоков ввода-вывода.
Часть

III

состоит из трех глав, посвященных технологии

такого же количества глав, посвященных технологии

Swing,
JavaFX.

а часть

IV -

из

Предисловие
Часть

V

31

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

Сначала в ней рассмотрены компоненты

Java Beans, а затем

Java.

представлены сервлеты.

Исходный код примеров, доступный в Интернете
Исходный код всех примеров, приведенных в этой книге, доступен в исходном

(английском) варианте ввода-вывода текста и комментариев на странице веб­
сайта издательства Oracle Press, посвященной этой книге, по следующему адресу:
https://www.mhprofessional.com/9781259589331-usa-java-thecomplete-reference-tenth-edition-group.

Особые благодарности
Выражаю особую благодарность Патрику Нотону
О'Нилу

(Joe O'Neil)

(Patrick Naughton),

Джо

и Дэнни Коварду

Патрик Нотон был одним из

(Danny Coward).
создателей языка Java.

Он помог мне в написании

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

21, 23

и

27

была

предоставлена Патриком. Его проницательность, опыт и энергия в огромной сте­

пени способствовали успеху этой книги.
При подготовке второго и третьего изданий этой книги Джо О'Нил предоста­
вил исходные черновые материалы, которые послужили основанием для написа­

ния глав

30, 32, 37

и

38.

Джо помогал мне при написании нескольких книг, и я вы­

соко ценю его вклад.

Дэнни Ковард выполнил научное редактирование книги. Он принимал участие

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

замечания и дельные предложения всегда были ценными и достойными большой
признательности.

Герберт Шилдт

Дополнительная литература
Настоящее издание открывает серию книг по программированию на

Java,

на­

писанных Гербертом Шилдтом. Ниже перечислены другие книги этого автора, ко­
торые могут вас заинтересовать.

• fava: методики

программирования Шилдта. И.Д. "Вильяме';

• fava 8: руководство

2008 r.

для начинающих, 6-е изд. И.Д. "Вильяме';



SWING: руководство



Искусство программирования на

для начинающих. И.Д. "Вильяме';



Iпtrodиciпg JavaFX

f ava.

И.Д. "Вильяме';

8 Programтiпg, Oracle Press, 2015

г.

2007 r.
2005 r.

2017 r.

Предисловие

32

От издательства
Вы, читатель этой книги, и есть главный ее критик и комментатор. Мы ценим

ваше мнение и хотим знать, что было сделано нами правильно, что можно было сде­
лать лучше и что еще вы хотели бы увидеть изданным нами. Нам интересно услы­

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

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

и обязательно учтем его при отборе и подготовке к изданию последующих книг.
Наши электронные адреса:

E-mail:

info@williamspuЫishing.com

'W~:

http://www.williamspuЫishing.com

ЧАСТЬ

1
ГЛАВА

ЯзыкJаvа

1

История и развитие
языкаJаvа

ГЛАВА2

Краткий обзор Java
ГЛАВАЗ
Типы данных, переменные
и массивы

ГЛАВА4
Операции
ГЛАВАS
Управляющие операторы

ГЛАВАб
Введение в классы
ГЛАВА

7

Подробное рассмотрение
классов и методов

ГЛАВА В
Наследование
ГЛАВА9

Пакеты и интерфейсы
ГЛАВА

10

Обработка исключений
ГЛАВА

11

Мноrопоточное
программирование

ГЛАВА 12
Перечисления,
автоупаковка и аннотации

ГЛАВА

13

Ввод-вывод, оператор

try с ресурсами
и прочие вопросы

ГЛАВА

14

Обобщения
ГЛАВА

15

Лямбда-выражения
ГЛАВА
Модули

16

'

ГЛАВА

История и развитие

1

языка

Java

Чтобы досконально изучить язык программирования

Java,

следует понять причи­

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

Java,

этот язык сочетает в себе лучшие элементы из своего богатого наследия

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

Java,

в том числе его синтаксису, библиотекам и приложениям,

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

Несмотря на то что язык

Java неразрывно связан с

Интернетом, важно помнить,

что это, прежде всего, язык программирования. Разработка и усовершенствование

языков программирования обусловлены двумя основными причинами:



адаптация к изменяющимся средам и областям применения;



реализация улучшений и усовершенствований в области программирования.

Как будет показано в этой главе, разработка языка

Java

почти в равной мере

была обусловлена обеими этими причинами.

Происхождение
Язык

Java

Java

тесно связан с языком С++, который, в свою очередь, является пря­

мым наследником языка С. Многие особенности
языков. От С язык

Java

Java унаследовал свой синтаксис,

унаследованы от обоих этих

а многие его объектно-ориен­

тированные свойства были перенесены из С++. Собственно говоря, ряд определя­
ющих характеристик языка

никшие потребности

-

Java

был перенесен

-

или разработан в ответ на воз­

из его предшественников. Более того, создание

Java

свои­

ми корнями уходит глубоко в процесс усовершенствования и адаптации, который
происходит в языках программирования на протяжении нескольких последних де­

сятилетий. Поэтому в этом разделе рассматривается последовательность событий

и факторов, приведших к появлению

Java.

Как станет ясно в дальнейшем, каждое

новшество в архитектуре языка, как правило, было обусловлено необходимостью

Часть 1. Язык Java

36

найти решение той или иной основной проблемы, которую не могли разрешить
существовавшие до этого языки. И язык

Java

не является исключением из этого

правила.

Зарождение современного программирования: язык С
Язык С буквально потряс компьютерный мир. Его влияние нельзя недооцени­
вать, поскольку он полностью изменил подход к программированию. Создание

языка С было прямым следствием потребности в структурированном, эффектив­
ном и высокоуровневом языке, который мог бы заменить код ассемблера в процес­
се создания системных программ. Как вы, вероятно, знаете, при проектировании
языка программирования часто приходится находить компромиссы между:





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

безопасностью и эффективностью;
устойчивостью и расширяемостью.

До появления языка С программистам, как правило, приходилось выбирать
между языками, которые позволяли оптимизировать тот или иной ряд характе­

ристик. Так, на языке

FORTRAN

можно было писать достаточно эффективные

программы для научных вычислений, но он не совсем подходил для написания

системного кода. Аналогично язык

BASIC

был очень прост в изучении, но у него

было не очень много функциональных возможностей, а недостаточная структу­
рированность ставила под сомнение его полезность для написания крупных про­

грамм. На языке ассемблера можно писать очень эффективные программы, но его

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

Еще одна усложнявшая дело проблема состояла в том, что первые языки про­

граммирования вроде

BASIC, COBOL

и

FORTRAN

были разработаны без учета

принципов структурирования. Вместо этого основными средствами управления

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

называемого "макаронного кода"

-

множества запутанных переходов и услов­

ных ветвей, которые делали программу едва ли доступной для понимания. И хотя

языки вроде

Pascal

структурированы, они не были предназначены для написания

эффективных программ и лишены ряда важных средств, необходимых для напи­
сания разнообразных программ. (В частности, применять

Pascal для

написания си­

стемного кода было нецелесообразно, принимая во внимание наличие нескольких
стандартных диалектов этого языка.)

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

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

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

37

Глава 1. История и развитие языка Java

к созданию более совершенного языка программирования. Но в то же время стало

все больше ощущаться влияние еще одного, очень важного фактора. Компьютеры,
наконец, получили достаточно широкое распространение, чтобы была достигну­
та "критическая масса': Компьютерное оборудование больше не находилось за за­

крытыми дверями. Впервые программисты получили буквально неограниченный
доступ к своим вычислительным машинам. Это дало свободу для эксперименти­
рования. Программисты смогли также приступить к созданию своих собственных
инструментальных средств. Накануне создания С произошел качественный скачок

в области языков программирования.
Язык С, изобретенный и впервые реализованный Деннисом Ритчи на мини­
Э ВМ

DEC PDP-11,

работавшей под управлением операционной системы

UNIX,

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

BCPL, разработанного Мартином

Ричардсом.

BCPL оказал влияние на язык,

получивший название В, который был изобретен Кеном Томпсоном и в начале
1970-х гг. привел к появлению языка С. В течение долгих лет фактическим стан­
дартом языка С была его версия, которая поставлялась вместе с операционной си­
стемой

UNIX

(она описана в книге Язык программирования С Брайана Кернигана

и Денниса Ритчи, 2-е издание, И.Д. "Вилямс':

2007 г.). Язык С был формально стан­
1989 г" когда Национальный институт стандартизации США
(American National Standards lnstitute - ANSI) принял стандарт на С.

дартизован в декабре

Многие считают создание С началом современного этапа развития языков про­

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

доставляли столько неприятностей в предыдущих языках. В итоrе появился мощ­

ный, эффективный, структурированный язык, изучение которого было сравни­
тельно простым. Кроме того, ему была присуща еще одна, почти непостижимая
особенность: он был разработан специально для программистов. До появления С
языки программирования проектировались в основном в качестве академических

упражнений или бюрократическими организациями. Иное дело

-

язык С. Он был

спроектирован, реализован и разработан практикующими программистами и от­
ражал их подход к проrраммированию. Его функции были отлажены, проверены
и многократно переработаны людьми, которые действительно пользовались этим

языком. Таким образом, получился язык, который сразу же понравился програм­

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

знание среди программистов. Короче говоря, С

-

это язык, разработанный про­

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

ную особенность унаследовал и язык

Java.

Следующий этап: язык С++
В конце 1970-х-начале 1980-х rг. язык С стал господствующим языком про­
граммирования и продолжает широко применяться до сих пор. А если С

-

удач­

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

38

Часть 1. Язык Java

грамм. На протяжении всей истории развития программирования постоянно ра­

стущая сложность программ порождала потребность в более совершенных спо­
собах преодоления их сложности. Язык С++ явился ответом на эту потребность.
Чтобы лучше понять, почему потребность преодоления сложности программ яв­
ляется главной побудительной причиной создания языка С++, рассмотрим следу­
ющие факторы.
С момента изобретения компьютеров подходы к программированию коренным
образом изменились. Когда компьютеры только появились, программирование
осуществлялось изменением двоичных машинных инструкций вручную с пане­
ли управления компьютера. До тех пор, пока длина программ не превышала не­

скольких сотен инструкций, этот подход был вполне приемлем. В связи с разрас­
танием программ был изобретен язык ассемблера, который позволил программи­

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

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

Первым языком программирования, который получил широкое распростране­

ние, был, конечно же,

FORTRAN.

Хотя он и стал первым впечатляющим этапом

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

зарождением структурного программирования. Эта методика программирования

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

когда они достигали определенных масштабов. К началу 1980-х. сложность многих
проектов начала превышать предел, позволявший справиться с ними, применяя

структурный подход. Для решения этой проблемы была изобретена новая мето­
дика программирования, получившая название объектно-ориентированного про­

граммирования (ООП). Объектно-ориентированное программирование подроб­
но рассматривается в последующих главах, а здесь приводится лишь краткое его

определение: ООП

-

это методика программирования, которая помогает органи­

зовывать сложные программы, применяя принципы наследования, инкапсуляции

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

предел его способности справляться со сложностью программ. Как только раз­
меры программы

превышают определенную величину,

она становится слишком

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

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

тельно, неуправляемой. Язык С++ предоставил возможности, которые позволили

Глава 1. История и развитие языка Java

39

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

Язык С++ был изобретен Бьярне Страуструпом (Bjaгne Stгoustrup) в
когда он работал в компании

Bell Laboratories

Джерси. Вначале Страуструп назвал новый язык "С
Но в

1983

1979

г.,

в городе Мюррей-Хилл, шт. Нью­

with Classes"

(С с классами).

г. это название было изменено на С++. Язык С++ расширяет функцио­

нальные возможности языка С, добавляя в него объектно-ориентированные свой­
ства. А поскольку язык С++ построен на основе С, то в нем поддерживаются все

функциональные возможности, свойства и преимущества С. Это обстоятельство
явилось главной причиной успешного распространения С++ в качестве языка про­

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

Предпосылки к созданию
К концу 1980-х и в начале 1990-х

Java

rr.

объектно-ориентированное программиро­

вание на С++ стало основной методикой программирования. И в течение некото­
рого, хотя и непродолжительного периода времени казалось, что программисты

наконец изобрели идеальный язык. Ведь язык С++ сочетал в себе высокую эффек­
тивность и стилистические элементы языка С наряду с объектно-ориентирован­

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

несколько лет, и развитие Всемирной паутины и Интернета достигло "критической

массы'; что и привело к еще одной революции в программировании.

Создание языка

Java

Начало разработке языка Java было положено в 1991 г. Джеймсом Гослингом
(James Gosling), Патриком Нотоном (Patrick Naughton), Крисом Уартом (Chris
Warth), Эдом Франком (Ed Frank) и Майком Шериданом (Mike Sheridan), работав­
шими в компании Sun Microsystems, Inc. Разработка первой рабочей версии заняла
18 месяцев. Вначале язык получил название "Oak" (Дуб), но в 1995 r. он был пере­
именован в "Java': Между первой реализацией языка Oak в конце 1992 r. и публич­
ным объявлением о создании Java весной 1995 г. в разработке и развитии этого
языка приняли участие немало других специалистов. В частности, Билл Джой (Bill
Joy), Артур ван Хофф (Arthur van Hoff), Джонатан Пэйн (Jonathan Payne), Франк
Йеллин (Frank Yellin) и Тим Линдхольм (Tim Lindholm) внесли основной вклад
в развитие исходного прототипа Java.
Как ни странно, первоначальной побудительной причиной для создания языка

Java

послужил совсем не Интернет, а потребность в независящем от конкретной

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

Часть 1. Язык Java

40

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

и С++ (как и большинства других языков) состоит в том, что написанные на них
программы должны компилироваться для конкретной платформы. И хотя про­

граммы на С++ могут быть скомпилированы практически для любого типа про­
цессора, тем не менее для этого потребуется наличие полного компилятора С++,
предназначенного для данного конкретного процессора. Но дело в том, что созда­

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

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

Java.

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

появился второй, еще более важный фактор, который должен был сыграть

Java,

решающую роль в судьбе этого языка. И этим вторым фактором, конечно же, стала

Всемирная паутина (веб). Если бы формирование веб не происходило почти одно­
временно с реализацией языка

Java,

он мог бы остаться полезным, но незамечен­

ным языком программирования бытовых электронных устройств. Но с появлени­

ем веб язык

Java

вышел на передний край разработки языков программирования,

поскольку среда веб также нуждалась в переносимых программах.

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

лательна. Несмотря на то что потребность в средствах для создания эффективных,
переносимых (не зависящих от конкретной платформы) программ существовала
в программировании с самого начала, она отодвигалась на задний план другими,

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

(Intel, Macintosh

и

UNIX),

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

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

к Интернету подключены разнотипные платформы, пользователям желательно,

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

К
мы

1993

г. членам группы разработчиков

переносимости,

часто

возникающие

при

Java

стало очевидно, что пробле­

создании

кода,

предназначенного

для встраивания в контроллеры, возникают также и при попытках создания кода

для Интернета. Фактически та же проблема, для решения которой в мелком мас­

штабе предназначался язык

Java,

была актуальна в большем масштабе и в среде

41

Глава 1. История и развитие языка Java
Интернета. Понимание этого обстоятельства вынудило разработчиков

Java

пере­

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

Java,

несмотря

на то, что потребность в архитектурно нейтральном языке программирования по­
служила для этого своего рода "первоначальной искрой':
Как упоминалось ранее, язык

Java

наследует многие из своих характеристик

от языков С и С++. Это сделано намеренно. Разработчики

Java

знали, что ис­

пользование знакомого синтаксиса С и повторение объектно-ориентированных

свойств С++ должно было сделать их язык привлекательным для миллионов,
имеющих опыт программирования на С/С++. Помимо внешнего сходства, в

Java

используется ряд других характерных особенностей, которые способствовали

успеху языков С и С++. Во-первых, язык

Java

был разработан, проверен и усовер­

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

Этот язык разработан с учетом потребностей и опыта его создателей. Таким об­
разом,

Java -

это язык для программистов. Во-вторых,

непротиворечив. В-третьих,

Java

Java

целостен и логически

предоставляет программисту полный контроль

над программой, если не учитывать ограничения, налагаемые средой Интернета.

Если программирование выполняется грамотно, это непосредственно отражается

на самих программах. В равной степени справедливо и обратное. Иначе говоря,

Java -

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

им профессионально.
Из-за сходства характеристик языков

Java

и С некоторые склонны считать

Java

просто "версией языка С++ для Интернета': Но это серьезное заблуждение. Языку

Java присущи значительные практические и концептуальные отличия. Язык С++ дей­
ствительно оказал влияние на характеристики Java, но Java не является усовершен­
ствованной версией С++. Например, Java несовместим с языком С++. Разумеется,
у него немало сходств с языком С++, и в исходном коде программы на Java програм­
мирующий на С++ будет чувствовать себя почти как дома. Вместе с тем язык Java
предназначен не для замены С++, а для решения одних задач, тогда как язык С++ для решения других задач. Оба языка будут еще долго сосуществовать.
Как отмечалось в начале этой главы, развитие языков программирования об­
условлено двумя причинами: адаптацией к изменениям в среде и реализацией

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

Java,

вызвали потребность в независящих от плат­

формы программах, предназначенных для распространения в Интернете. Но язык

Java изменяет также подход к написанию программ.

В частности, язык

Java углубил

и усовершенствовал объектно-ориентированный подход, использованный в С++,
добавил в него поддержку многопоточной обработки и предоставил библиотеку,
которая упростила доступ к Интернету. Но столь поразительный успех

Java

об­

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

работки программ для Интернета язык

Java стал тем,

чем язык С стал для систем­

ного программирования: революционной силой, которая изменила мир.

Часть 1. Язык Java

42

Связь с языком С#
Многообразие и большие возможности языка

Java продолжают

оказывать вли­

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

вы любого нового языка. Успех

Java

слишком значителен, чтобы его можно было

игнорировать.

Вероятно, наиболее наглядным примером влияния языка Java на программирова­
Microsoft для поддержки платформы

ние служит язык С#. Он создан в корпорации

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

Java

и С# имеется

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

опыление"

Java и

С# служит наилучшим доказательством того, что язык

Java корен­

ным образом изменил представление о языках проrраммирования и их применении.

Каким образом язык Java повлиял на Интернет
Интернет способствовал выдвижению
ния, а язык

Java

Java,

Java

на передний край программирова­

в свою очередь, оказал очень сильное влияние на Интернет. Язык

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

вил появление нового типа прикладных программ, предназначенных для работы
в сети и получивших название аплетов, которые изменили понятие содержимого

сетевой среды. Кроме того, язык

Java

позволил решить две наиболее острые про­

блемы программирования, связанные с Интернетом: переносимость и безопас­

ность. Рассмотрим каждую из этих проблем в отдельности.

Аплеты на
Аплет

-

Java

это особый вид прикладной программы на

Java,

предназначенный

для передачи через Интернет и автоматического выполнения в совместимом с

Java

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

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

ряд функций со стороны сервера на сторону клиента.
Появление

аплетов

изменило

характер

программирования

приложений

для Интернета, поскольку они расширили совокупность объектов, которые можно

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

Глава 1. История и развитие языка Java

43

подразумевает просмотр пассивных данных. Даже при загрузке программы ее код
по-прежнему остается пассивными данными до тех пор, пока он не начнет выпол­

няться. И напротив, аплет представляет собой динамическую, автоматически вы­
полняющуюся прикладную программу. Такая программа является активным аген­
том на клиентской машине, хотя она инициируется сервером.

На ранней стадии развития
граммирования на

Java,

Java.

Java аплеты были самой важной составляющей про­

Они демонстрировали эффективность и преимущества

повышали привлекательность веб-страниц и давали программистам возмож­

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

Java.

И хотя аплеты

находят применение и ныне, со временем они потеряли свое значение. Как поясня­
ется далее в книге, начиная с версии

JDK 9, аплеты постепенно выходят из употре­

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

Безопасность
За привлекательностью динамических сетевых программ скрываются серьез­

ные трудности обеспечения безопасности и переносимости. Очевидно, что кли­

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

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

станет ясно в дальнейшем, эти трудности эффективно и изящно решаются в

Java.

Рассмотрим их подробнее, начиная с безопасности.

Вам, вероятно, известно, что каждая загрузка обычной программы сопряжена
с риском, поскольку загружаемый код может содержать вирус, "троянский конь"
или вредоносный код. Дело в том, что вредоносный код может сделать свое чер­
ное дело, если получит несанкционированный доступ к системным ресурсам.

Например, просматривая содержимое локальной файловой системы компьютера,

вирусная программа может собирать конфиденциальную информацию вроде но­
меров кредитных карточек, сведений о состоянии банковских счетов и паролей.

Для безопасной загрузки и выполнения аплетов

Java на клиентской машине нужно

было предотвратить подобные атаки со стороны аплетов.

Java

обеспечивает такую защиту, ограничивая действие аплета исполняющей

средой Java и не предоставляя

ему доступ к другим частям операционной системы

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

и не нарушит ее безопасность, многие специалисты и пользователи считают наи­
более новаторским аспектом

Java.

Переносимость
Переносимость

-

основная особенность Интернета, поскольку эта глобаль­

ная сеть соединяет вместе множество разнотипных компьютеров и операционных

Часть 1. Язык Java

44

систем. Чтобы программа на

Java

могла выполняться практически на любом ком­

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

рационных систем и браузеров, подключенных к Интернету. А создавать разные
версии аплетов для разнотипных компьютеров совершенно нерационально. Один

и тот же код должен работать на всех компьютерах. Поэтому требовался какой-то
механизм для создания переносимого исполняемого кода. Как станет ясно в даль­

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

Чудо

Java: байт-код

Основная особенность

которая позволяет решать описанные выше проб­

Java,

лемы обеспечения безопасности и переносимости программ, состоит в том, что
компилятор

Java выдает

не исполняемый код, а так называемый байт-код

-

в выс­

шей степени оптимизированный набор инструкций, предназначенных для выпол­
нения в исполняющей системе

Viгtual

Java,

называемой виртуальной машиной

Java (Java

Machine - JVM). Собственно говоря, первоначальная версия виртуальной
JVM разрабатывалась в качестве интерпретатора байт-кода. Это может

машины

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

компиляторы

многих современных языков

программирования

создавать исполняемый код. Но то, что программа на

туальной машиной

JVM,

Java

призваны

интерпретируется вир­

как раз помогает решить основные проблемы разработки

программ для Интернета. И вот почему.

Трансляция программы

Java

в байт-код значительно упрощает ее выполнение

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

JVM.

Если в отдельной системе имеется исполня­

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

JVM

Java.

Следует, однако,

на разных платформах, несмотря

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

Java

компилирова­

лась в машинозависимый код, то для каждого типа процессоров, подключенных

к Интернету, должны были бы существовать отдельные версии одной и той же
программы. Ясно, что такое решение неприемлемо. Таким образом, организация

выполнения байт-кода виртуальной машиной

JVM -

простейший способ созда­

ния по-настоящему переносимых программ.

Тот факт, что программа на

Java выполняется виртуальной

JVM, спо­
JVM управ­

машиной

собствует также повышению ее безопасности. Виртуальная машина

ляет выполнением программы, поэтому она может изолировать программу, что­

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

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

способствует повышению безопасности.

Java,

также

Глава 1. История и развитие языка Java

45

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

JVM,

она выполняется медленнее, чем если

бы она была скомпилирована в исполняемый код. Но в

Java

это отличие в произ­

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

JVM выполнять программы

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

Java

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

оперативно выполнять компиляцию байт-кода в машинозависимый код для по­
вышения производительности. Поэтому вскоре после выпуска

технология

HotSpot,

Java

появилась

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

называемый ДТ-компилятор) байт-кода. Если динамический компилятор входит

в состав виртуальной машины

JVM,

то избранные фрагменты байт-кодакомпи­

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

емый код нецелесообразна, поскольку

Java в

исполня­

Java производит различные проверки,

кото­

рые могут быть сделаны только во время выполнения. Вместо этого динамический
компилятор компилирует код во время выполнения по мере надобности. Более
того, компилируются не все фрагменты байт-кода, а только те, которым компи­
ляция принесет выгоду, а остальной код просто интерпретируется. Тем не менее
принцип динамической компиляции обеспечивает значительное повышение про­

изводительности. Даже при динамической компиляции байт-кода характеристики
переносимости и безопасности сохраняются, поскольку виртуальная машина

JVM

по-прежнему отвечает за целостность исполняющей среды.

Но, начиная с версии
компилятор,

JDK 9,

предназначенный

в избранные среды
для

компиляции

Java

включен статический

байт-кода в

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

JVM,

платформенно­

а не динамически.

Статическая компиляция имеет свои особенности и не подменяет собой описан­
ный выше традиционный подход, принятый в

Java.

Более того, статической ком­

пиляции присущи свои ограничения. Так, на момент написания настоящего из­
дания

книги

статическая

компиляция

применялась лишь

целях и была доступна только в версиях

Java

в

экспериментальных

для 64-разрядных ОС

Linux,

а пред­

варительно скомпилированный код должен был выполняться в той же самой (или

аналогично сконфигурированной) системе, где он был скомпилирован. Таким об­
разом, статическая компиляция ограничивает переносимость кода. В силу своего
слишком специализированно характера статическая компиляция не рассматрива­

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

Выход за пределы аплетов
Как пояснялось ранее, на ранней стадии развития

тью программирования на

Java.

Java аплеты

были важной час­

Они не только повысили привлекательность веб­

страниц, но и стали самой заметной особенностью

Java,

заметно повысив его при­

тягательность. Тем не менее аплеты опираются на подключаемый к браузеру модуль

Java.

Поэтому для нормальной работы аплета он должен поддерживаться брау-

46

Часть 1. Язык Java

зером. Отныне подключаемый к браузеру модуль

Java

больше не померживается.

Проще говоря, без такой поддержки со стороны браузера аплеты нежизнеспособны.
Вследствие этого, начиная с версии

JDK 9,

поддержка аплетов в

Java считается уста­

ревшей. В языке Jаvаустаревшим считается средство, которое по-прежнему доступ­

но, но отмечено как не рекомендованное к употреблению. Такое языковое средство
будет исключено в последующем выпуске

Java.

Следовательно, не рекомендованные

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

ловно, является технология

Java Web Start,

которая позволяет динамически загру­

жать приложение из веб-страницы. Отличие заключается в том, что приложение

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

Java.

Технология

Java Web Start предоставляет меха­
Java.

низм развертывания, пригодный для работы со многими типами программ на

И хотя подробное обсуждение стратегий развертывания выходит за рамки насто­
ящего издания книги, краткое введение в технологию

Java Web Start в

силу ее важ­

ности приведено в приложении Б.

Сервлеты: серверные программы на

Java

Как ни полезны аплеты, они решают лишь половину задачи в архитектуре "кли­

ент-сервер': Вскоре после появления языка

Java стало очевидно, что он может при­
- это неболь­

годиться и на серверах. В результате появились сервлеты. Сервлет
шая прикладная программа, выполняемая на сервере.

Сервлеты служат для создания динамически генерируемого содержимого, ко­
торое затем предоставляется клиенту. Например, интерактивный склад может

использовать сервлет для поиска стоимости товара в базе данных. Затем инфор­

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

CGI (Common Gateway Interface -

интерфейс общего

шлюза}, применение сервлетов дает ряд преимуществ, в том числе повышает про­
изводительность.

Подобно всем программам на

Java, сервлеты компилируются в байт-код и вы­
JVM, поэтому они в высшей степени переноси­

полняются виртуальной машиной

мы. Следовательно, один и тот же сервлет может применяться в различных сервер­

ных средах. Единственным необходимым условием для этого является поддержка
на сервере виртуальной машины

Терминология

JVM и

контейнера для сервлета.

Java

Рассмотрение истории создания и развития языка
описания терминологии, характерной для
шим изобретение

Java,

Java.

Java

было бы неполным без

Основным фактором, обусловив­

стала потребность в обеспечении переносимости и без­

опасности, но свою роль в формировании окончательной версии языка сыграли

Глава 1. История и развитие языка Java
и другие факторы. Группа разработчиков обобщила основные понятия

Java

47
в сле­

дующем перечне терминов:













простота;

безопасность;
переносимость;

объектная ориентированность;
надежность;
многопоточность;

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

Мы уже рассмотрели такие термины, как безопасность и переносимость. А те­
перь поясним значение остальных терминов.

Простота
Язык

Java был задуман

как простой в изучении и эффективный в употреблении

профессиональными программистами. Овладеть языком

Java

тем, у кого имеется

некоторый опыт программирования, не составит особого труда. Если вы уже зна­
комы с основными принципами объектно-ориентированного программирования,

то изучить
на С++,

Java вам будет еще проще. А от тех, кто имеет опыт программирования
переход к Java вообще потребует минимум усилий. Язык Java наследует

синтаксис С/С++ и многие объектно-ориентированные свойства С++, поэтому

для большинства программистов изучение

Java не

составит больших трудностей.

Объектная ориентированность
Хотя предшественники языка

Java и оказали влияние

на его архитектуру и син­

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

коду с каким-нибудь другим языком. Это позволило группе разработчиков созда­
вать

Java,

по существу, с чистого листа. Одним из следствий этого явился четкий,

практичный, прагматичный подход к объектам. Помимо того, что язык

Java

поза­

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

середины между строгим соблюдением принципа "все элементы программы яв­
ляются объектами" и более прагматичного принципа "прочь с дороги': Объектная
модель

Java

проста и легко расширяема. В то же время такие элементарные типы

данных, как целочисленные, сохраняются в виде высокопроизводительных компо­

нентов, не являющихся объектами.

48

Часть 1. Язык Java

Надежность
Многоплатформенная среда веб предъявляет к программам повышенные тре­
бования, поскольку они должны надежно выполняться в разнотипных системах.

Поэтому способность создавать надежные программы была одним из главных при­
оритетов при разработке

Java.

Для обеспечения надежности в

Java

налагается ряд

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

Java

избавляет от необходимости беспокоиться по поводу многих наиболее часто встре­
чающихся ошибок программирования. А поскольку

строго типизированный

Java -

язык, то проверка кода выполняется во время компиляции. Но проверка кода де­

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

Предсказуемость кода в разных ситуациях

-

Java.
Java.
Java, рас­

одна из основных особенностей

Чтобы понять, каким образом достигается надежность программ на

смотрим две основные причины программных сбоев: ошибки управления памятью
и неправильная обработка исключений (т.е. ошибки при выполнении). В традици­
онных средах создания программ управление памятью

-

сложная и трудоемкая

задача. Например, в среде С/С++ программист должен вручную резервировать

и освобождать всю динамически распределяемую память. Иногда это ведет к воз­

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

Java полностью

исключает такие

ситуации, автоматически управляя резервированием и освобождением памяти.
(Освобождение оперативной памяти полностью выполняется автоматически, по­

скольку

Java

предоставляет средства сборки неиспользуемых объектов в "мусор':)

В традиционных средах условия для исключений часто возникают в таких ситуа­

циях, как деление на нуль или отсутствие искомого файла, а управление ими долж­
но осуществляться с помощью громоздких и трудных для понимания конструк­

ций.

Java

облегчает выполнение этой задачи, предлагая объектно-ориентирован­

ный механизм обработки исключений. В грамотно написанной программе на

Java

все ошибки при выполнении могут (и должны) обрабатываться самой программой.

Многопоточность
Язык

Java

был разработан в ответ на потребность создавать интерактивные се­

тевые программы. Для этой цели в

Java померживается

написание многопоточных

программ, способных одновременно выполнять многие действия. Исполняющая
система

Java содержит изящное, но вместе с тем сложное решение задачи синхрони­

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

рактивные системы. Простой подход к организации многопоточной обработки, реа­
лизованный в

Java,

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

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

49

Глава 1. История и развитие языка Java

Архитектурная нейтральность
Основной задачей, которую ставили перед собой разработчики

Java, было

обес­

печение долговечности и переносимости кода. Одной из главных трудностей, сто­

явших перед разработчиками, когда они создавали

Java,

было отсутствие всяких

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

-

даже

на одном и том же компьютере. Операционные системы и процессоры постоян­

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

языке и виртуальной машине

Java.

Они поставили перед собой следующую цель:

"Написано однажды, выполняется везде, в любое время и всегда': И эта цель была
в значительной степени достигнута.

Интерпретируемость и высокая производительность
Как упоминалось ранее, выполняя компиляцию программ в промежуточное

представление, называемое байт-кодом,

Java

позволяет создавать межплатфор­

менные программы. Такой код может выполняться в любой системе, которая ре­
ализует виртуальную машину

JVM.

С первых же попыток разработать межплат­

форменные решения удалось достичь поставленной цели, хотя и за счет снижения
производительности. Как пояснялось ранее, байт-код

Java

был тщательно разра­

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

сохраняют все преимущества кода,

Java,

обеспечи­

не зависящего

от конкретной платформы.

Распределенность
Язык

Java

предназначен для распределенной среды Интернета, поскольку он

поддерживает семейство сетевых протоколов

TCP/IP.

По существу, обращение

к ресурсу по унифицированному указателю информационного ресурса

(URL) мало
Java поддерживается также удален­
(Remote Method Invocation - RMI). Такая возможность позво­

чем отличается от обращения к файлу. В языке
ный вызов методов

ляет вызывать методы из программ через сеть.

Динамичность
Программы на

Java содержат значительный объем данных динамического типа,

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

мя выполнения. Это позволяет безопасно и рационально выполнять динамическое
связывание кода. Данное обстоятельство исключительно важно для устойчивости

среды

Java,

где небольшие фрагменты байт-кода могут динамически обновляться

в действующей системе.

Часть 1. Язык Java

50

Эволюция языка
Первоначальная версия

Java
Java

не представляла собой ничего особенно револю­

ционного, но она и не ознаменовала завершение периода быстрого совершенство­

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

Java про­
Java 1.0 разра­

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

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

ботчики уже создали версию

Java 1.1.

Внедренные в этой версии функциональные

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

разработчики добавили много новых библиотечных элементов, переопределили
механизм обработки событий и изменили конфигурацию многих библиотечных
средств из версии

1.0.

Кроме того, они отказались от нескольких средств, перво­

начально определенных в

зом, в версии

Java 1.1

Java 1.0,

но признанных затем устаревшими. Таким обра­

были внедрены новые характерные свойства и в то же время

исключены некоторые свойства, определенные в первоначальной спецификации.

Следующей основной стала версия

Java 2, где номер "2" означает второе поко­
Java 2 стало знаменательным событием, означавшим на­
эпохи" Java. Первой версии Java 2 был присвоен номер 1.2, что

ление. Создание версии

чало "современной

может показаться несколько странным. Дело в том, что вначале номер относил­

ся к внутреннему номеру версии библиотек

Java, но затем он был распространен
Java 2 компания Sun Microsystems
начала выпускать программное обеспечение Java в виде пакета J2SE (Java 2 Platform
Standard Edition - Стандартная версия платформы Java 2), и с тех пор номера вер­
на всю версию в целом. С появлением версии

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

В версии

Java 2 была добавлена поддержка ряда новых средств, в том числе
Collections Framework. Кроме того, были усовершенствованы виртуаль­
ная машина JVM и различные инструментальные средства программирования.
В то же время версия Java 2 содержала некоторые не рекомендованные к употре­
блению средства. Наибольшие изменения претерпел класс Thread, где методы
suspend (), resume () и stop () стали рекомендованными к употреблению в мно­

Swing

и

гопоточном программировании.

Версия

Java J2SE.

J2SE 1.3 стала первой серьезной

модернизацией первоначальной версии

Эта модернизация состояла, главным образом, в расширении существу­

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

1.3

1.2

и

1.3,

совместимы по исходному

оказалось меньше, чем в трех предшествую­

щих основных версиях, это не сделало ее менее важной.

Совершенствование языка

Java

было продолжено в версии

J2SE 1.4.

Эта вер­

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

assert,

цепочки исключений и под­

система ввода-вывода на основе каналов. Изменения были внесены и в каркас

Collections Fгamework,

а также в классы, предназначенные для работы в сети. В эту

версию было также внесено много мелких изменений. Несмотря на значительное

Глава 1. История и развитие языка Java
количество новых функциональных возможностей, версия

1.4

51

почти полностью

сохранила совместимость по исходному коду с предшествующими версиями.

В следующую версию

Java,

названную

J2SE 5,

был внесен ряд революционных

изменений. В отличие от большинства предшествующих обновлений

Java, которые
J2SE 5 была

предоставляли важные, но постепенные усовершенствования, в версии

коренным образом расширена область, возможности и пределы применения язы­

ка. Чтобы стало понятнее, насколько существенными оказались изменения, вне­
сенные в версии

J2SE 5,

ниже перечислены лишь самые основные из новых функ­

циональных возможностей

Java в данной версии.

Обобщения.











Аннотации.
Автоупаковка и автораспаковка.
Перечисления.
Усовершенствованный цикл

for

Аргументы переменной длины

в стиле

for each.

(varargs).

Статический импорт.
Форматированный ввод-вывод.

Утилиты параллельной обработки.

В этом перечне не указаны незначительные изменения или постепенные усо­
вершенствования. Каждый пункт перечня представлял значительное дополнение

языка

Java.

Одни из них, в том числе обобщения, усовершенствованный цикл

for

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

Аннотации придали программированию совершенно новые черты. В любом случае
влияние всех этих дополнений вышло за рамки их прямого действия. Они полнос­

тью изменили сам характер языка

Java.

Значение новых функциональных возможностей нашло отражение в присвоен­

ном данной версии номере

- "5': Если следовать привычной логике, то следующим
Java должен был быть 1.5. Однако новые средства оказались столь
значительными, что переход от версии 1.4 к версии 1.5 не отражал бы масштабы
внесенных изменений. Поэтому в компании Sun Micгosystems решили присвоить
новой версии номер 5, чтобы тем самым подчеркнуть значимость этого события.
Поэтому версия данного программного продукта была названа J2SE 5, а комплект
разработчика - JDK 5. Тем не менее для сохранения единообразия в компании
Sun Microsystems решили использовать номер 1.5 в качестве внутреннего номера
версии, называемого также номером версии разработки. Цифра 5 в обозначении
номером версии

версии называется номером версии продукта.
Следующая версия получила название
пании

Java.

Sun Microsystems

В названии была опущена цифра

называется сокращенно

Java SE 6.

С выходом этой версии в ком­

решили в очередной раз изменить название платформы

fava SE,

2.

Таким образом, данная платформа теперь

а официально

- fava Platform, Standard Edition 6

Часть

52

(Платформа

1. Язык Java

Java,

стандартная версия

Как и в обозначении версии

6.

J2SE 5,

6).

Комплект разработчика был назван

цифра



JDK

названии

Java SE 6 означает номер
1.6.
J2SE 5 с рядом дальнейших

версии продукта. Внутренним номером разработки этой версии является
Версия

Java SE 6

была построена на основе версии

усовершенствований. Она не содержала дополнений к числу основных языковых

средств

но расширяла библиотеки

Java,

API,

добавляя несколько новых пакетов

и предоставляя ряд усовершенствований в исполняющей системе. В этой версии

было сделано еще несколько усовершенствований и внесено несколько дополне­
ний. В целом версия

Java SE 6 призвана закрепить достижения в J2SE 5.
Java SE 7 с комплектом разработчика Java JDK 7
и внутренним номером версии 1.7. Это был первый главный выпуск Java с тех пор,
как компания Sun Microsystems была приобретена компанией Oracle. Версия Java SE 7
Далее была выпущена версия

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

тек

Java API.

В данной версии была усовершенствована исполняющая система

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

на

Java больше

Java,

Java,

но программирующих

интересовали дополнения, внесенные в сам язык и его библиотеку.

Новые языковые средства были разработаны в рамках проекта

Project Coin.

Этот проект должен был обозначать многие так называемые "мелкие" изменения

в

Java,

которые предполагалось включить в

JDK 7,

хотя эффект от всех этих новых

"мелких" новшеств весьма велик с точки зрения их воздействия на код. В действи­
тельности для большинства программистов эти изменения могут стать самым
важным нововведением в

внедренные в

Java SE 7.

Ниже перечислены новые языковые средства,

JDK 7.



Расширение типа





Двоичные целочисленные литералы.

ре

String

возможностями управлять ветвлением в операто-

switch.

Символы подчеркивания в числовых литералах.

Расширение оператора

try,

называемое оператором

try

с ресурсами, обе­

спечивающее автоматическое управление ресурсами. (Например, потоки

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



Выводимость типов (с помощью ромбовидного оператора

< >)

при создании

обобщенного экземпляра.



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

catch

(многократ­

ный перехват), а также улучшенный контроль соответствия типов повторно
генерируемых исключений.



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

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

Java,

Project Coin,

счи­

в целом они тем не менее дают мно-

53

Глава 1. История и развитие языка Java

го больше преимуществ, чем подразумевает само понятие "мелкие': В частности,
оператор

try

с ресурсами оказывает существенное влияние на порядок написания

кода, опирающегося на потоки ввода-вывода. Кроме того, возможность использо­

вать объекты типа

String

в операторе

switch

оказалась долгожданным усовер­

шенствованием, позволившим во многом упростить код.

В версии

Java SE 7

внесено несколько дополнений в библиотеку

Java API.
NIO Framework и до­
полнения каркаса Fork!Join Framework. Новая система ввода-вывода NIO (перво­
начально называвшаяся New 110) была внедрена в версии Java 1.4. Но изменения,
внесенные в версии Java SE 7, значительно расширили возможности этой системы,
причем настолько, что она зачастую обозначается как NI0.2.
Каркас Fork/Join Framework обеспечивает важную поддержку параллельного
Важнейшими из них являются усовершенствования каркаса

программирования. Термином параллельное программирование обычно обозна­
чаются технологии, повышающие эффективность применения компьютеров с не­
сколькими процессорами, включая многоядерные системы. Преимущества, кото­
рые дают многоядерные системы, позволяют в перспективе значительно повысить

производительность программ. Каркас

Fork/Join

Framewoгk позволяет решать за­

дачи параллельного программирования в следующих областях:



упрощение составления и использования заданий, которые могут выпол­
няться параллельно;



автоматическое использование нескольких процессоров.

Следовательно, с помощью каркаса

Fork/Join Framework

можно создавать при­

ложения, в которых автоматически используются процессоры, доступные в испол­

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

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

Следующей была выпущена версия
и внутренним номером версии

1.8.

Java SE 8

с комплектом разработчика

JDK 8

Значительные усовершенствования в ней про­

изошли благодаря внедрению лямбда-выражений

-

нового языкового средства

с далеко идущими последствиями. Лямбда-выражения позволяют совершенно ина­
че подходить к программированию и написанию кода. Как поясняется более под­

робно в главе

15,

лямбда-выражения вносят в

Java

возможности функционального

программирования. В процессе программирования лямбда-выражения способны

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

лямбда-выражения вводят в язык новую операцию

(- >) и

элемент синтаксиса.

Внедрение лямбда-выражений оказало обширное влияние и на библиотеки Java,
которые были дополнены новыми средствами, выгодно использующими лямбда­
выражения. К наиболее важным новшествам в библиотеке
прикладной программный интерфейс

кет j

API

Java

относится новый

потоков ввода-вывода, входящий в па­

ava. util. stream. В этом прикладном интерфейсе API, оптимизированном

с учетом лямбда-выражений, поддерживаются конвейерные операции с данными.
Еще одним важным новшеством является пакет

j ava. util. function,

в кото-

54

Часть 1. Язык Java

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

Java API

внедрены и дру­

гие, менее значительные средства, имеющие отношение к лямбда-выражениям.
Еще одно нововведение, навеянное лямбда-выражениями, касается интерфей­
сов. В версии

JDK 8 появилась возможность определять реализацию по умолчанию

метода, объявленного в интерфейсе. Если конкретная реализация такого метода

отсутствует, то используется его реализация по умолчанию в интерфейсе. Таким
образом, обеспечивается постепенное развитие интерфейсов, поскольку новый

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

в

JDK 8, относятся новый

прикладной программный интерфейс

API для обработки

даты и времени, типовые аннотации и возможность использовать параллельную

обработку при сортировке массива. Кроме того, в состав

JDK 8 включена поддерж­
ка JavaFX 8 - последней версии нового каркаса приложений Java с графическим
пользовательским интерфейсом (ГПИ). Предполагается, что каркас JavaFX ста­
нет неотъемлемой частью практически всех приложений Java и в конечном итоге
заменит Swing для разработки большинства проектов на основе ГПИ. Введение
в JavaFX представлено в части IV данной книги.

Версия

Java SE 9

Самой последней выпущена версия

9.

При выпуске

JDK 9 внутренний

Java SE 9

с комплектом разработчика

номер версии также оказался равным

9.

JDK

В ком­

плекте

JDK 9 представлен главный выпуск Java, включая существенные улучшения
Java, так и его библиотек. Подобно выпускам JDK 5 и JDK 8, выпуск JDK 9
оказал значительное влияние не только на язык Java, но и на его библиотеки.
Главным нововведением в версии JDK 9 являются модули, позволяющие указы­
как языка

вать взаимосвязи и зависимости в прикладном коде, а также расширяющие воз­

можности управления доступом в

Java.

Вместе с модулями в языке

Java

появился

новый синтаксический элемент и несколько ключевых слов. Кроме того, в состав

JDK

была включена утилита j

link,

ния образ прикладного файла типа

позволяющая создавать на стадии выполне­

JMOD,

содержащего только нужные модули.

Модули также оказали заметное влияние на библиотеку
чиная с версии

JDK 9,

Java API,

поскольку, на­

библиотечные пакеты организованы в модули.

Несмотря на то что модули являются главным усовершенствованием
сии

9, они принципиально просты

Java в вер­

и понятны. А поскольку модули совсем не нару­

шают помержку кода, унаследованного из предыдущих версий

Java,

то их нетруд­

но внедрить в процесс текущей разработки. Для этого не придется сразу вносить
изменения в уже существующий код. Короче говоря, модули значительно расширя­

ют функциональные возможности, не меняя существо языка

Java.
JDK 9 вошло многих других новых средств. Особый
интерес представляет утилита JShell, поддерживающая экспериментирование
с программами и изучение языка Java в интерактивном режиме. (Введение в JShell
Помимо модулей, в состав

55

Глава 1. История и развитие языка Java

приведено в приложении В к настоящему изданию книги.) Еще одним интересным
новшеством является поддержка закрытых интерфейсных методов. Их внедрение
дополнительно расширило поддержку методов с реализацией по умолчанию, по­

явившихся в версии

В версии

JDK 8.

JDK 9

возможности утилиты

расширены средствами поиска, а также новым дескриптором

держки. Как и в предыдущих выпусках, в версии

шенствования библиотек

Java API.
Java

Как правило, в любом выпуске

-

для их под­

были продолжены усовер­

можно обнаружить новые средства, привле­

кающие наибольшее внимание. Но версии
бенность

JDK 9

j avadoc были

@index

присуща одна существенная осо­

JDK 9

упразднение аплетов. Начиная с версии

JDK 9, аплеты

больше не реко­

мендованы для применения в новых проектах. Как пояснялось ранее в этой главе,

весь прикладной интерфейс

API

для аплетов не рекомендован в

JDK 9 для

приме­

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

на

Java

в Интернете рекомендуется технология

Java Web

Staгt. В связи с тем что

аплеты упразднены и не рекомендуются для применения в новом коде, они больше
не упоминаются далее в настоящем издании, хотя краткое введение в аплеты при­

ведено в приложении Г к книге.
Подводя краткий итог, можно сказать, что
дений в

Java,

JDK 9 продолжает наследие

нововве­

помогающих сохранить живость и проворство, которые пользователи

уже привыкли ожидать от этого языка программирования. Материал настоящего

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

(JDK 9), со

Java SE 9

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

ными в соответствующих местах книги.

Культура нововведений
С самого начала язык

первоначальная

версия

Java

оказался в центре культуры нововведений. Его

трансформировала

для Интернета. Виртуальная машина

Java (JVM)

подход

к

программированию

и байт-код совершенно измени­

ли представление о безопасности и переносимости. Переносимый код вдохнул
жизнь в веб. Процесс

Java Community Pгocess (JCP) преобразовал способ внедре­
Java никогда не оставалась без из­
течение длительного периода времени. И Java SE 9 остается на момент

ния новых идей в язык. Область применения
менений в

выхода этого издания из печати самой последней версией в непрекращающемся
динамичном развитии

Java.

ГЛАВА

Краткий обзор Java

2

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

Java существуют

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

Java,

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

Java.

Приведенный в ней материал по­

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

Java.

Большинство рассмотренных в этой главе вопросов будут подробнее обсуждаться
в остальных главах данной части.

Объектно-ориентированное программирование
Объектно-ориентированное программирование (ООП) составляет основу Java.

По существу, все программы на
ентированными. Язык

Java

Java

являются в какой-то степени объектно-ори­

связан с ООП настолько тесно, что, прежде чем при­

ступить к написанию на нем даже простейших программ, следует вначале ознако­

миться с основными принципами ООП. Поэтому начнем с рассмотрения теорети­

ческих вопросов ооп.

Две парадигмы
Все компьютерные программы состоят из двух элементов: кода и данных. Более

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

"что происходит'; а других

-

тем, "на что оказывается влияние': Существуют две па­

радигмы создания программ. Первая из них называется моделью, ориентированной
на процессы, и характеризует программу как последовательность линейных шагов

(т.е. кода). Модель, ориентированную на процессы, можно рассматривать в качестве

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

1,

подобный подход по­

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

58

Часть 1. Язык Java
С целью преодолеть увеличение сложности программ была начата разработка

подхода, называемого объектно-ориентированным программированием. Объектно­
ориентированное программирование позволяет организовать программу вокруг ее

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

Абстракция
Важным элементом ООП является абстракция. Человеку свойственно пред­

ставлять сложные явления и объекты, прибегая к абстракции. Например, люди
представляют себе автомобиль не в виде набора десятков тысяч отдельных дета­

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

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

на более управляемые части. Внешне автомобиль выглядит единым объектом. Но
стоит заглянуть внутрь, как становится ясно, что он состоит из нескольких подси­

стем: рулевого управления, тормозов, аудиосистемы, привязных ремней, обогрева­

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

ит в том, что структуру автомобиля (или любой другой сложной системы) можно
описать с помощью иерархических абстракций.
Иерархические абстракции сложных систем можно применять и к компьютер­

ным программам. Благодаря абстракции данные традиционной, ориентированной
на процессы, программы можно преобразовать в составляющие ее объекты, а по­

следовательность этапов процесса

-

в совокупность сообщений, передаваемых

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

Java,

так и восприятия мира человеком.

Важно понимать, каким образом эти принципы реализуются в программах. Как станет

ясно в дальнейшем, ООП является еще одной, но более эффективной и естественной
парадигмой создания программ, способных пережить неизбежные изменения, сопро­

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

Глава 2. Краткий обзор Java

59

Три принципа ООП
Все языки объектно-ориентированного программирования предоставляют ме­
ханизмы, облегчающие реализацию объектно-ориентированной модели. Этими
механизмами являются инкапсуляция, наследование и полиморфизм. Рассмотрим
эти принципы ООП в отдельности.

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

снаружи оболочки. Доступ к коду и данным, находящимся внутри оболочки, строго
контролируется тщательно определенным интерфейсом. Чтобы провести анало­

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

рычага переключения скоростей. Пользователь (в данном случае водитель) может
оказывать влияние на эту сложную инкапсуляцию только одним способом: пере­
мещая рычаг переключения скоростей. На коробку передач нельзя воздействовать,
например, с помощью индикатора поворота или дворников. Таким образом, рычаг
переключения скоростей является строго определенным, а по существу, единствен­

ным интерфейсом с коробкой передач. Более того, происходящее внутри коробки
передач не влияет на объекты, находящиеся вне ее. Например, переключение пере­
дач не включает фары! Функция автоматического переключения передач инкапсу­
лирована, и поэтому десятки изготовителей автомобилей могут реализовать ее как
угодно. Но с точки зрения водителя все эти коробки передач работают одинаково.
Аналогичный принцип можно применять и в программировании. Сильная сторона
инкапсулированного кода состоит в следующем: всем известно, как получить доступ

к нему, а следовательно, его можно использовать независимо о подробностей реали­

зации и не опасаясь неожиданных побочных эффектов.
Основу инкапсуляции в

Java

составляет класс. Подробнее классы будут рассмо­

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

использоваться набором объектов. Каждый объект данного класса содержит струк­
туру и поведение, которые определены классом, как если бы объект был "отлит"

в форме класса. Поэтому иногда объекты называют экземплярами класса. Таким об­
разом, класс

-

это логическая конструкция, а объект

-

ее физическое воплощение.

При создании класса определяются код и данные, которые образуют этот класс.
Совместно эти элементы называются членами класса. В частности, определенные
в классе данные называются переменными-членами или переменными экземпляра,

а код, оперирующий данными,
программирующие на

Java

-

методами-членами или просто методами. (То, что

называют методами, программирующие на С/С++ назы­

вают функциями.) В программах, правильно написанных на

Java,

методы определяют,

60

Часть 1. Язык Java

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

классе. Каждый метод или переменная в классе могут быть помечены как закрытые
или открытые. Открытый интерфейс класса представляет все, что должны или мо­
гут знать внешние пользователи класса. Закрытые методы и данные могут быть до­
ступны только для кода, который является членом данного класса. Следовательно,

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

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

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

2.1).

Класс

о
Открытые
переменные экземпляра

(не рекомендуются)

д
Открытые методы

д
Закрытые методы

Закрытые переменные экземпляра

Рис.

2.1.

/

д

д/д\

д

о

о
о

Инкапсуляция: открытые методы можно

использовать для защиты закрытых данных

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

ской (т.е. нисходящей) классификации. Например, золотистый ретривер

-

часть

Глава 2. Краткий обзор Java

61

классификации собак, которая, в свою очередь, относится к классу млекопитаю­

щих, а тот

-

к еще большему классу животных. Без иерархий каждый объект дол­

жен был бы явно определять все свои характеристики. Но благодаря наследованию
объект должен определять только те из них, которые делают его особым в клас­

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

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

способности и костная система. Животным присущи также определенные особен­
ности поведения: они едят, дышат и спят. Такое описание свойств и поведения со­
ставляет определение класса животных.

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

тип зубов и молочных желез. Такое определение называется подклассом живот­
ных, которые относятся к суперклассу (родительскому классу) млекопитающих.
А поскольку млекопитающие

-

лишь более точно определенные животные, то они

наследуют все свойства животных. Подкласс нижнего уровня иерархии классов
наследует все свойства каждого из его родительских классов (рис.

2.2).

Животные

(
Рис.

2.2. Иерархия

классов животных

Наследование связано также с инкапсуляцией. Если отдельный класс инкапсулиру­

ет определенные свойства, то любой его подкласс будет иметь те же самые свойства

плюс любые дополнительные свойства, определяющие его специализацию (рис.

2.3).

Благодаря этому ключевому принципу сложность объектно-ориентированных про-

Часть 1. Язык Java

62

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

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

Млекопитающие

Собачьи

Гончая?

Домашние

Охотничьи

Лабрадор
Лабрадор
Возраст

Период беременности

Гончая?

Пол

Охотничьи навыки

Выученная для утиной охоты?

Вес

Длина хвоста

Наличие родословной?

Количество детенышей

Дворовые/комнатные

Рис.

2.3. Лабрадор полностью наследует инкапсулированные
свойства всех родительских классов животных

Глава 2. Краткий обзор Java

63

Полиморфизм
Полиморфизм (от греч. "много форм")

-

это принцип ООП, позволяющий ис­

пользовать один и тот же интерфейс для общего класса действий. Каждое действие
зависит от конкретной ситуации. Рассмотрим в качестве примера стек, действую­

щий как список обратного магазинного типа. Допустим, в программе требуются
стеки трех типов: для целочисленных значений, для числовых значений с плаваю­
щей точкой и для символов. Алгоритм реализации каждого из этих стеков остает­

ся неизменным, несмотря на отличия в данных, которые в них хранятся. В языке,

не являющемся объектно-ориентированным, для обращения со стеком пришлось
бы создавать три разных ряда подпрограмм под отдельными именами. А в языке

Java

благодаря принципу полиморфизма для обращения со стеком можно опреде­

лить общий ряд подпрограмм под одними и теми же общими именами.

В более общем смысле принцип полиморфизма нередко выражается фразой
"один интерфейс, несколько методов': Это означает, что можно разработать об­
щий интерфейс для группы связанных вместе действий. Такой подход позволя­
ет уменьшить сложность программы, поскольку один и тот же интерфейс служит

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

-

полиморфное свойство. Если собака почувствует запах кошки, она залает

и погонится за ней. А если собака почувствует запах своего корма, то у нее начнет­
ся слюноотделение, и она поспешит к своей миске. В обоих случаях действует одно

и то же чувство обоняния. Отличие лишь в том, что именно издает запах, т.е. в типе
данных, воздействующих на нос собаки! Этот общий принцип можно реализовать,
применив его к методам в программе на

Java.

Совместное применение полиморфизма,
инкапсуляции и наследования

Если принципы полиморфизма, инкапсуляции и наследования применяются

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

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

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

Из двух приведенных ранее примеров из реальной жизни пример с автомобиля­
ми более полно иллюстрирует возможности ООП. Если пример с собаками впол­
не подходит для рассмотрения ООП с точки зрения наследования, то у примера

Часть 1. Язык Java

64

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

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

гом переключения передач, большинство людей могут даже оценить отличия руч­
ной коробки передач от автоматической, поскольку они имеют ясное представле­

ние об общем родительском классе этих объектов

-

системе передач.

Пользуясь автомобилями, люди постоянно взаимодействуют с их инкапсу­
лированными характеристиками. Педали тормоза и газа скрывают невероятную

сложность соответствующих объектов за настолько простым интерфейсом, что
для управления этими объектами достаточно нажать ступней педаль! Конкретная
реализация двигателя, тип тормозов и размер шин не оказывают никакого влия­

ния на порядок взаимодействия с определением класса педалей.

И наконец, полиморфизм ясно отражает способность изготовителей автомоби­

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

с защитой от блокировки или традиционные тормоза, рулевая система с гидро­
усилителем или с реечной передачей и

4-, 6-

или 8-цилиндровые двигатели. Но

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

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

Как отмечалось в начале этого раздела, каждая программа на
ектно-ориентированной. Точнее говоря, в каждой программе на

Java является объ­
Java применяются

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

приведенных в остальной части этой главы и ряде последующих глав, тем не менее

они в них присутствуют. Как станет ясно в дальнейшем, многие языковые средства

Java являются составной частью встроенных библиотек классов, в которых широко
применяются принципы инкапсуляции, наследования и полиморфизма.

Первый пример простой программы
А теперь, когда разъяснены самые основы объектно-ориентированного харак­
тера

Java,

рассмотрим несколько практических примеров программ, написанных

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

Глава 2. Краткий обзор Java

65

/*
Это

простая

Присвоить

программа

исходному

на

файлу

Java.
имя

"Example.java"

*/

class Example {
// Эта программа начинается с вызова метода main()
puЬlic static void main(String args[])
{
System.out.println("Пpocтaя программа на Java.");

На заметку! Здесь и далее используется стандартный комплект разработчика

(JDK 9),

предоставляемый компанией

Oracle.

Java SE 9 Developer's Кit
Java приме­

Если же для написания программ на

няется интегрированная среда разработки (ИСР), то для компиляции и выполнения программ

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

Ввод кода программы
Для большинства языков программирования имя файла, который содержит ис­
ходный код программы, не имеет значения. Но в

Java дело

обстоит иначе. Прежде

всего следует твердо усвоить, что исходному файлу очень важно присвоить имя.
В данном примере исходному файлу должно быть присвоено

Example. java.

И вот почему.

В языке

Java исходный файл официально

называется единицей компиляции. Он,

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

содержащими только один класс.) Компилятор
имел расширение

Java требует, чтобы

исходный файл

• j ava.

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

определенный в ней класс также называется

Example.

И это не случайно. В

Java

весь код должен размещаться в классе. По принятому соглашению имя главного

класса должно совпадать с именем файла, содержащего исходный код програм­

мы. Кроме того, написание имени исходного файла должно точно соответствовать
имени главного класса, включая строчные и прописные буквы. Дело в том, что
в коде

Java учитывается регистр

букв. На первый взгляд, соглашение о строгом со­

ответствии имен файлов и классов может показаться произвольным. Но на самом
деле оно упрощает сопровождение и организацию программ.

Компиляция программы
Чтобы скомпилировать программу

Example,

запустите компилятор

(javac),

указав имя исходного файла в командной строке следующим образом:

C:\>javac Example.java
Компилятор

j avac

создаст файл

Example. class,

кода. Как пояснялось ранее, байт-код

Java

содержащий версию байт­

является промежуточным представле-

Часть 1. Язык Java

66

нием программы, содержащим инструкции, которые будет выполнять виртуаль­
ная машина

JVM.

Следовательно, компилятор

javac

выдает результат, который

не является непосредственно исполняемым кодом.

Чтобы выполнить программу, следует воспользоваться загрузчиком прило­
жений

Java,

который называется

java.

Ему нужно передать имя класса

Example

в качестве аргумента командной строки, как показано ниже.

C:\>java Example
Выполнение данной программы приведет к выводу на экран следующего ре­
зультата:
Простая

программа

Java.

на

В процессе компиляции исходного кода каждый отдельный класс помещается

в собственный выходной файл, называемый по имени класса и получающий рас­
ширение

• class.

Поэтому исходным файлам программ на

Java

целесообразно

присваивать имена, совпадающие с именами классов, которые содержатся в фай­
лах с расширением

• class.

При запуске загрузчика приложений

j ava описанным

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

с указанным именем и расширением

• class.

И если он найдет такой файл, то вы­

полнит код, содержащийся в указанном классе.

Подробный анализ первого примера программы
Хотя сама программа

Example. j ava небольшая, с ней связано несколько важ­
Java. Проанализируем под­

ных особенностей, характерных для всех программ на

робно каждую часть этой программы. Начинается эта программа со следующих
строк:

/*
Это

простая

Присвоить

программа

исходному

Java.

на

файлу

имя

"Example.java"

*/

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

Java

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

в ее исходный файл. Компилятор игнорирует содержимое комментариев. Эти
комментарии описывают или поясняют действия программы для тех, кто про­

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

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

Example. j ava.

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

В языке

Java

поддерживаются три вида комментариев. Комментарий, приве­

денный в начале программы, называется многострочным. Этот вид комментариев
должен начинаться со знаков

/

* и оканчиваться знаками * /. Весь текст, располо­

женный между этими двумя парами символов, игнорируется компилятором. Как

Глава 2. Краткий обзор Java

67

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

Перейдем к следующей строке кода анализируемой здесь программы. Ниже по­
казано, как она выглядит.

class Example {
В этой строке кода ключевое слово

деляемого класса, а

Example -

class

служит для объявления вновь опре­

в качестве идентификатора, обозначающего имя

класса. Все определение класса, в том числе его членов, должно располагаться

между открывающей

( {)

и закрывающей

фигурными скобками. Мы не станем

(})

пока что останавливаться на особенностях реализации класса. Отметим только,
что в среде

Java

все действия программы выполняются в пределах класса. В этом

и состоит одна из причин, по которым все программы на

Java

являются (по край­

ней мере, частично) объектно-ориентированными.
Следующая строка кода данной программы содержит однострочный коммен­
тарий:

11

Эта

программа

начинается

с

вызова

main()

метода

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

/ /,

Java.

Он называется одно­

а завершается знаком конца

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

-

для коротких, построч­

ных описаний. Третий вид комментариев, называемый документирующим, будет
рассмотрен далее в разделе "Комментарии':
Перейдем к следующей строке кода анализируемой здесь программы. Ниже по­
казано, как она выглядит.

puЬlic

static void main(String args[ ] )

Эта строка кода начинается с объявления метода

rnain

().Как следует из пред­

шествующего ей комментария, выполнение программы начинается именно с этой

строки кода. Выполнение всех прикладных программ на
метода

rnain

Java

начинается с вызова

().Мы не станем пока что разъяснять подробно назначение каждого

элемента этой строки, потому что для этого требуется ясное представление о под­
ходе к инкапсуляции, принятом в

Java.

Но поскольку эта строка кода присутствует

в большинстве примеров из данной части книги, то проанализируем ее вкратце.
Ключевое слово puЬlic является модификатором доступа, который дает про­
граммисту возможность управлять видимостью членов класса. Когда члену класса
предшествует ключевое слово puЫic, этот член доступен из кода за пределами

класса, где он определен. (Совершенно противоположное обозначает ключевое
слово

private -

оно не разрешает доступ к члену класса из кода за предела­

ми данного класса.) В данном случае метод

rnain ()

должен быть определен как

puЬlic, поскольку при запуске программы он должен вызываться из кода за пре­
делами его класса. Ключевое слово

static

позволяет вызывать метод

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

JVM

main ()
main () вы­

перед созданием любых объектов. А ключе-

Часть 1. Язык Java

68

вое слово

void

просто сообщает компилятору, что метод

main ( )

не возвращает

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

Java будут подробно

рассматриваться в последующих главах.

Как указывалось выше, метод

программ на

Java.

букв. Следовательно, имя
в виду, что компилятор

main

вызывается при запуске прикладных

main ()

Java

учитывается регистр

имени main.

Следует также иметь

Следует, однако, иметь в виду, что в

Main

Java

не равнозначно

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

(),но загрузчик приложений

сов. Так, если вместо имени

main

(java)

не сможет выполнить код таких клас­

Main, компилятор все равно скомпи­
ava выдаст сообщение об ошибке,
метод main ().

ввести имя

лирует программу, но загрузчик приложений j
поскольку ему не удалось обнаружить

Для передачи любой информации, требующейся методу, служат переменные,
указываемые в скобках вслед за именем метода. Эти переменные называются па­
раметрами. Если параметры не требуются методу, то указываются пустые скобки.

main () имеется единственный, хотя и довольно сложный параметр. Так,
String args [] объявляется параметр args, обозначающий мас­
сив экземпляров класса String. (Массивы - это коллекции похожих объектов.)
В объектах типа String хранятся символьные строки. В данном случае параметр
args принимает любые аргументы командной строки, присутствующие во время

У метода

в выражении

выполнения программы. В рассматриваемом здесь примере программы эта ин­

формация, вводимая из командной строки, не используется, но в других, рассма­
триваемых далее примерах программ она будет применяться.
Последним элементом в рассматриваемой здесь строке кода оказывается сим­

вол открывающей фигурной скобки ( {).Он обозначает начало тела метода main

().

Весь код, составляющий тело метода, должен располагаться между открывающей

и закрывающей фигурными скобками в определении этого метода.
Еще один важный момент: метод

main ()

служит всего лишь началом програм­

мы. Сложная программа может включать в себя десятки классов, но только один

из них должен содержать метод

main

(),чтобы программу можно было запустить

на выполнение. И хотя в некоторых типах программ метод

main ( )

вообще не тре­

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

main ().

System.out.println("Пpocтaя

программа

на

Java.");

В этой строке кода на консоль (а по существу, на экран) выводится символьная
строка "Простая программа на

Java."

с последующим переходом на новую

строку. На самом деле вывод текста на консоль выполняется встроенным мето­

дом

println

().В данном случае метод

println ()

отображает переданную ему

символьную строку. Как будет показано далее, с помощью этого метода на консоль

69

Глава 2. Краткий обзор Java

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

ется с обозначения стандартного потока вывода

System. out. Это слишком слож­

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

Java,

но вкратце

System обозначает предопределенный класс, пре­
out - поток вывода, связанный с консолью 1 •
в реальных программах на Java консольный вывод­

доставляющий доступ к системе, а
Нетрудно догадаться, что

ввод применяется редко. Многие современные вычислительные среды по своему

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

В дальнейшем будут рассмотрены другие способы ввода-вывода данных в

Java, а до

тех пор будут применяться методы консольного ввода-вывода.

Обратите

println

внимание

на то,

что

оператор,

в

котором

(),завершается точкой с запятой. В языке

Java

вызывается

метод

все операторы обычно

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

остальных строк кода программы состоит в том, что формально они не являются
операторами. Первый знак
деление класса

} завершает метод ma in ( ) , а последний знак } -

опре­

Example.

Второй пример короткой программы
Вероятно, ни одно другое понятие не является для языка программирования
столь важным, как понятие переменных. Как вы, скорее всего, знаете, перемен­

ная

-

это именованная ячейка памяти, которой может быть присвоено значение

в программе. Во время выполнения программы значение переменной может из­

меняться. В следующем примере программы демонстрируются способы объявле­
ния переменной и присвоения ей значения. Этот пример демонстрирует также ряд

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

Example2 • j ava.

/*
Это

еще

один

Присвоить

пример

исходному

короткой

файлу

имя

программы.

"Example2.java"

*/

class Example2 {
1 На

самом деле для вывода результатов на консоль кириллицей в начале каждой програм­

мы следует ввести приведенную ниже строку кода, чтобы установить кодировку СР866



Windows),

поскольку в

Java

по умолчанию выбирается кодировка

ющая намного большее количество символов

{65536 по

сравнению

UTF-16, поддержива­
256 символами в коди­

ровке СР866).

System.setOut(new PrintStrearn(System.out,

true,

"ср866"));

Нужную кодировку можно указать и при запуске программы на выполнение из командной
строки, например:

java -Dconsole.encoding=cp866

иня_исходного_файла

Подробнее о кодировках символов речь пойдет в главах

3 и 18. -

Примеч. ред.

70

Часть 1. Язык Java

static void main(String args[])
int num; // в этой строке кода объявляется
// переменная с именем num
num = 100; // в этой строке кода переменной num
// присваивается значение 100

puЬlic

System.out.println("Этo

num

=

переменная

num:

"

+

num);

num * 2;

System.out.print("Знaчeниe

переменной

num * 2

равно

");

System.out.println(num);

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

Это

num: 100
num * 2

переменная

Значение

переменной

200

равно

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

int num;

//
//

в

этой

строке

переменная

с

кода

объявляется

именем

num

В этой строке кода объявляется целочисленная переменная

num.

В языке

Java,

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

тип

имя_переменной;

В этом объявлении тип обозначает конкретный тип объявляемой переменной,
а имя_переменной -

заданное имя переменной. Если требуется объявить не­

сколько переменных заданного типа, это можно сделать в виде разделенного за­

пятыми списка имен переменных. В языке

Java

определен целый ряд типов дан­

ных, в том числе целочисленный, символьный и числовой с плавающей точкой.

Ключевое слово

int

обозначает целочисленный тип. В приведенной ниже строке

кода с комментариями из рассматриваемого здесь примера программы перемен­

ной

num присваивается значение 1 О О. Операция присваивания обозначается в Java

одиночным знаком равенства.

num

=

100; //
//

в

этой

строке

присваивается

кода

переменной

значение

num

100

В следующей строке кода на консоль выводится значение переменной
торому предшествует символьная строка "Это
System.out.println("Этo

переменная

num:

переменная

"

+

num,

ко­

num: ":

num);

В этом операторе знак+ присоединяет значение переменной

num в

конце пред­

шествующей ему символьной строки, а затем выводится результирующая строка.

Глава 2. Краткий обзор Java
(На самом деле значение переменной

num

71

сначала преобразуется из целочислен­

ного в строковый эквивалент, а затем объединяется с предшествующей строкой.
Подробнее этот процесс описывается далее в книге.) Такой подход можно обоб­
щить. С помощью операции+ в одном вызове метода

можно объеди­

println ()

нить нужное количество символьных строк.

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

менной

n um

присваивается хранящееся в ней значение, умноженное на

большинстве других языков программирования, в

Java знак

2.

Как и в

* обозначает арифме­

тическую операцию умножения. После выполнения этой строки кода переменная

num будет содержать

значение

2 О О.

Ниже приведены две следующие строки кода из рассматриваемого здесь при­
мера программы.

System.out.print("Знaчeниe

переменной

num * 2

равно

");

System.out.println(num);
В них выполняется ряд новых действий. В частности, метод
ется для вывода символьной строки "Значение переменной

print ()
num * 2

вызыва­
равно".

После этой строки не следует знак новой строки. Таким образом, следующий ре­
зультат будет выводиться в той же самой строке. Метод
логично методу

println (),за

pr in t ( )

действует ана­

исключением того, что после каждого вызова он

не выводит знак новой строки. А теперь рассмотрим вызов метода

println ().

Обратите внимание на то, что имя переменной num указывается буквально. Методы

print () и println ()
Java типов данных.

могут служить для вывода значений любых встроенных

в

Два управляющих оператора
И хотя управляющие операторы подробно описываются в главе

5,

в этом раз­

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

послужат хорошей иллюстрацией важного аспекта

Условный оператор
Оператор

Java -

3 и 4.

Кроме того, они

блоков кода.

i f

i f действует подобно условному оператору в любом другом языке

программирования. Более того, его синтаксис такой же, как и условных операто­

ров

i f

в языках С, С++ и С#. Простейшая форма этого оператора выглядит следу­

ющим образом:
if(условие)

оператор;

где условие обозначает логическое выражение. Если условие истинно, то опера­
тор выполняется. А если условие ложно, то оператор пропускается. Рассмотрим
следующую строку кода:

if(num

<

100) System.out.println("num

меньше

100");

Часть 1. Язык Java

72

num содержит значение меньше 10 О, то
println ().А если переменная
равное 1 О О, то вызов метода р r i n t l n ( )

Если в данной строке кода переменная

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

n um

содержит значение, большее или

пропускается.

Как будет показано в главе

4,

в языке

Java

определен полный набор операций

сравнения, которые можно использовать в условном выражении. Некоторые из

них перечислены в табл.

Таблица

2.1.

2.1. Некоторые операции сравнения в Java
Меньше

<
>

Больше
Равно

Следует, однако, иметь в виду, что проверка на равенство обозначается двой­
ным знаком равенства(==). Ниже приведен пример программы, где демонстриру­
ется применение условного оператора

i f.

/*
Продемонстрировать
Присвоить

исходному

применение
файлу

имя

условного

оператора

if.

"IfSample.java"

*/

class IfSample {
puЬlic static void main(String args[])
int х, у;
х

= 10;

у

20;
у)

теперь

// этот оператор не будет ничего выводить
if(x ==у) System.out.println("вы не увидите

этого");

Эта программа выводит следующий результат:
х

меньше

у

х

теперь

равно

х

теперь

больше

у

у

Обратите внимание на еще одну особенность данного примера программы. В
строке кода

int

х,

у;

Глава 2. Краткий обзор Java

73

объявляются две переменные: х и у. Для этого используется список, разделяемый
запятыми.

Оператор цикла

f or

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

5,

в

Java

померживаются разно­

образные операторы цикла. И, вероятно, наиболее универсальным среди них яв­
ляется оператор цикла
fоr(инициализация;

for.

Ниже приведена простейшая форма этого оператора.

условие;

итерация)

оператор;

В этой чаще всего встречающейся форме инициализация обозначает началь­
ное значение переменной управления циклом, а условие-логическое выражение
для проверки значения переменной управления циклом. Если результат проверки

условия истинен, то выполнение цикла

f or

продолжается. А если результат этой

проверки ложен, то выполнение цикла прекращается. Выражение итерация опре­
деляет порядок изменения переменной управления циклом на каждом его шаге.
В приведенном ниже кратком примере программы демонстрируется применение
оператора цикла

for.

/*
Продемонстрировать

Присвоить

применение

исходному

файлу

имя

цикла

for.

"Forтest.java"

*/

class ForTest
puЬlic static void main(String args[])
int х;
for(x

=

О;

х>
>>>

Сдвиг вправо

> 4 = Ох"
+ hex((c >> 4) & OxOf] + hex[c
System.out.println(" Ь >>> 4 = Ох"
+ hex[(d >> 4) & OxOf] + hex(d
System.out.println(" (Ь & Oxff) >> 4 =
+ hex((e >> 4) & OxOf] + hex(e

& OxOf]);

& OxOf]);
& OxOf]);
Ох"

& OxOf]);

Как следует из приведенного ниже результата выполнения данной программы,
операция>>> не оказывает никакого воздействия на значения типа

byte. Сначала

в данном примере программы переменной Ь присваивается произвольное отрица­

тельное значение типа
менной Ь типа

byt е,

byte.

Затем переменной с присваивается значение пере­

сдвинутое на четыре позиции вправо и равное Ох f

ствие расширения знака. Далее переменной

Ь типа

f

вслед­

d присваивается значение переменной

byte, сдвинутое на четыре позиции вправо

без знака. Это значение должно

Глава 4. Операции
было бы быть равно Ох О f, но в действительности оно оказывается равным

123
Oxf f

из-за расширения знака, которое произошло при продвижении типа переменной Ь
к типу

int

перед сдвигом. И в последнем выражении переменной е присваивается

значение переменной Ь типа

byte,

сначала замаскированное до

8

двоичных раз­

рядов с помощью поразрядной логической операции И, а затем сдвинутое вправо

на четыре позиции. В итоге получается предполагаемое значение Ох О f. Обратите
внимание на то, что операция беззнакового сдвига вправо не применяется к зна­
чению переменной

d,

поскольку состояние знакового двоичного разряда известно

после выполнения поразрядной логической операции И.
Ь

>> 4
Ь >>> 4
Oxff) >> 4
Ь



&

Oxfl
Oxff
Oxff
OxOf

Поразрядные составные операции с присваиванием
Подобно арифметическим операциям, все двоичные поразрядные операции

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

а

=

а

>>

а

>>=

4;

4;

Равнозначны и следующие две операции, присваивающие переменной а резуль­
тат выполнения поразрядной логической операции а ИЛИ Ь:
а

=

а

1=

1

а

Ь;

Ь;

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

использует составные побитовые операторы с присваиванием для манипулирова­
ния этими переменными:

class OpBitEquals {
puЬlic static void main ( String args [])
int а
1;
int Ь
2;
int с
3;
а

1= 4;

ь

с

>>=
=

Больше или равно

),

которая

применяется в лямбда-выражениях.

Таблица

4.7. Предшествование операций в Java

Наивысшее
предшествование

++(постфиксная
операция)

-- (постфиксная
операция)

++ (префиксная
операция)

операция)

*

/

--

(префиксная

+(унарная
операция)

%

+
>>

>>>



>=

<

!=
&:

"
&:&:

11
?:

->
операция=

Наинизшее
предшествование

>

+ 3

Ь

Сначала в этом выражении к значению переменной Ь добавляется значение

3

1

а затем двоичные разряды значения переменной а сдвигаются вправо на получен­

ное в итоге количество позиций. Используя избыточные круглые скобки, это вы­
ражение можно было бы записать следующим образом:
а>>



+ 3)

Но если требуется сначала сдвинуть двоичные разряды значения переменной
а вправо на Ь позиций, а затем добавить

3

к полученному результату, то круглые

скобки следует использовать так, как показано ниже.


>>

+ 3

Ь)

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

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


1 4
1

+

с

(((4

>>

Ь

& 7

+с)»

Ь)

&

7))

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

ГЛАВА

5

Управляющие
операторы

В языках программирования управляющие операторы применяются для реа­
лизации переходов и ветвлений в потоке исполнения команд программы, исходя

из ее состояния. Управляющие операторы в программе на

Java

можно разделить

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

переменной. Операторы цикла позволяют повторять выполнение одного или не­

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

Java.

Операторы выбора
В языке

Java

поддерживаются два оператора выбора:

if

и

swi tch.

Эти опе­

раторы позволяют управлять порядком выполнения команд программы в соот­

ветствии с условиями, которые известны только во время выполнения. Читатели

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

Условный оператор

if

В этой главе подробно рассматривается условный оператор
ставленный в главе
помощью

можно

2.

if,

вкратце пред­

Это оператор условного ветвления программы на

направить

выполнение

программы

по

двум

Java.

разным

С его

ветвям.

Общая форма этого условного оператора выглядит следующим образом:

if

(условие)

е

е

l s

оператор,;

опера тор_.;

Здесь каждый опера тор обозначает одиночный или составной оператор, за­
ключенный в фигурные скобки (т.е. блок кода); условие вращающее логическое значение типа

обязательно.

boolean.

любое выражение, воз­

А оператор

else

указывать не­

Часть 1. Язык Java

132

Условный оператор

действует следующим образом: если условие истинно,

i f

то выполняется оператор,, а иначе

-

оператор 2 , если таковой имеется. Но ни

в коем случае не будет выполняться и тот, и другой оператор. Рассмотрим в каче­
стве примера следующий фрагмент кода:

int
/ /

а,

Ь;

...

if(a <
else Ь

Ь)

=

а=

О;

О;

Если в данном примере значение переменной а меньше значения переменной
Ь, то нулевое значение устанавливается в переменной а, а иначе

-

в переменной

Ь. Но ни в коем случае нулевое значение не может быть установлено сразу в обеих
переменных, а и Ь.

Чаще всего в выражениях, управляющих выполнением оператора

i f,

применя­

ются операции отношения, хотя это и не обязательно. Для управления условным
оператором

if

можно применять и одиночную переменную типа

boolean,

как

показано в следующем фрагменте кода:

boolean

dataAvailaЬle;

11

if

(dataAvailaЬle)

ProcessData();
else
waitForMoreData();
Следует, однако, иметь в виду, что после ключевого слова

i f

или е 1 s е допуска­

ется указывать только один оператор. Если же требуется ввести больше операто­
ров, то придется написать код так, как показано в приведенном ниже примере, где

оба оператора находятся в блоке кода. Они будут выполняться лишь в том случае,
если значение переменной bytesAvailaЫe окажется больше нуля.

int

bytesAvailaЫe;

11

if

(bytesAvailaЫe

>

0)

ProcessData();
bytesAvailaЫe

-= n;

else
waitForMoreData();
Некоторые программисты предпочитают использовать в условном операторе

i f фигурные скобки даже при наличии только одного оператора в каждом выра­
жении. Это упрощает добавление операторов в дальнейшем и избавляет от необ­

ходимости проверять наличие фигурных скобок. На самом деле пропуск опреде­

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

фрагмент кода:

int
11
if

bytesAvailaЬle;
(bytesAvailaЬle

> 0)

ProcessData();
bytesAvailaЫe

n;

Глава

5. Управляющие операторы

133

else
waitForMoreData();
bytesAvailaЫe = n;
Если судить по величине отступа, то в данном примере кода изначально пред­
полагалось, что оператор bytesAvailaЫe=n;

оператора

else.

Но не следует забывать, что в

должен выполняться в ветви

Java

отступы не имеют никакого

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

общений, но во время выполнения он будет вести себя не так, как предполагалось.
В приведенном ниже фрагменте кода исправлена ошибка, допущенная в предыду­
щем примере.

int

bytesAvailaЬle;

/ /

if

(bytesAvailaЬle

> 0)

ProcessData();

bytesAvailaЫe -= n;
else {
waitForMoreData();
bytesAvailaЬle = n;

Вложенные условные операторы

i f

Вложеннымназывается такой условный оператор

другого условного оператора
операторы

i f

операторами

i f

не следует забывать, что оператор

шим условным оператором

if(i == 10) {
if(j < 20) а= Ь;
if(k > 100) с = d; //
else а = с;
11
d;

а

который является целью

встречаются очень часто. Но, пользуясь вложенными условными

if,

if,

11
11

else

всегда связан сближай­

находящимся в том же самом блоке кода и еще не

связанным с другим оператором

else

i f,

или е 1 s е. В программах вложенные условные

else.

этот условный

оператор

связан

с

данным

а

этот

оператор

с

оператором

if

оператором

else,

else if(i == 10)

Как следует из комментариев к данному фрагменту кода, внешний оператор
е 1 s е не связан с оператором

i f (j

<

2 О ) , поскольку тот

не находится в том же

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

if,

который еще не связан с оператором

else.

оператор е 1 s е связан с оператором

i f (i

связан с оператором

поскольку тот является ближайшим к нему

i f (k > 1О О ),

в том же самом блоке кода.

==1 О

).

Следовательно, внешний

А внутренний оператор е 1 s е

Часть 1. Язык Java

134

Конструкция
Конструкция

if-else-if

i f - е l s е- i f, состоящая из последовательности вложенных ус­
i f, весьма распространена в программировании. В общем

ловных операторов

виде она выглядит следующим образом:

if

(условие)
оператор;

else

if(условие)

оператор;

else

if(условие)

оператор;

else
оператор;

Условные операторы

i f

выполняются последовательно, сверху вниз. Как только

одно из условий, управляющих оператором

i f,

оказывается равным

няется оператор, связанный с данным условным оператором
конструкции

i f - еl s е- i f

ется (т.е. не равно

true),

i f,

true,

выпол­

а остальная часть

пропускается. Если ни одно из условий не удовлетворя­

то выполняется заключительный оператор

else.

Этот по­

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

ратор

else.

Если же заключительный оператор

верки всех остальных условий равен

false,

else

не указан, а результат про­

то не производятся никакие действия.

Ниже приведен пример программы, в которой конструкция

i f - еl sе- i f

для определения времени года, к которому относится конкретный месяц.
//Продемонстрировать применение конструкции if-else-if
class IfElse {
puЬlic static void main ( String args [])
{
int month = 4; // Апрель
String season;
if (month == 12 1 1 month == 1 1 1 month == 2)
season = 11 зиме 11 ;
5)
else if(month - - 3 1 month
4 1 1 month
season = "весне";
7 1 1 month
8)
else if(month -- 6 11 month
season = "лету 11 ;
10 1 1 month - - 11)
else if(month - - 9 1 1 month
season
"осени 1 ';
else
"вымышленным месяцам";
season

System.out.println(
"Апрель

относится

к"

+

season

Эта программа выводит следующий результат:
Апрель

относится

к

весне

+

".");

ел ужит

Глава 5. Управляющие операторы

135

Прежде чем продолжить чтение, поэкспериментируйте с этой программой.

Убедитесь сами, что, независимо от значения, присвоенного переменной
в конструкции

if-else-if

month,

будет выполняться только одна операция присваи­

вания.

Оператор
В языке

swi tch

Java

оператор

swi tch

является оператором ветвления. Он предостав­

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

sw i t ch

оказывается эффективнее длинных последовательностей операторов в конструк­
ции

i f -else-i f.

switch
case
11

Общая форма оператора

swi tch

имеет следующий вид:

(выражение)
значение,:

последовательность

операторов

break;
case значение :
11

последовательность

операторов

break;

case
11

значение 11 :
последовательность

операторов

break;
default:
11

последовательность

Во всех версиях

short, in t, char
ве

Java

до

операторов

JDK 7 указанное

по

умолчанию

выражение должно иметь тип

byte,

или перечислимый тип. (Перечисления рассматриваются в гла­

12.) А начиная с JDK 7,

выражение может также иметь тип

чение, определенное в операторах ветвей выбора

S tr ing. Каждое зна­
case, должно быть однозначным

константным выражением (например, литеральным значением). Дублирование
значений в операторах ветвей выбора

case

не допускается. Каждое значение

должно быть совместимо по типу с указанным выражением.
Оператор

switch

действует следующим образом. Значение выражения срав­

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

case.

При обнаруже­

нии совпадения выполняется последовательность кода, следующая после операто­

ра данной ветви выбора
ветвей выбора

case

case.

Если значения ни одной из констант в операторах

не совпадают со значением выражения, то выполняется опе­

ратор выбора по умолчанию

default.

Но указывать этот оператор необязатель­

но. Если совпадений со значениями констант в операторах ветвей выбора
происходит, а оператор

de f а u 1 t

case

не

отсутствует, то никаких дальнейших действий

не выполняется.

Оператор

break

служит для

в ветвях выбора оператора

break,

прерывания последовательности операторов

swi tch.

Как только очередь доходит до оператора

выполнение продолжается с первой же строки кода, следующей после все-

136

Часть 1. Язык Java

го оператора

switch.

Таким образом, оператор

ленного выхода из оператора
нения оператора

swi tch.

break

предназначен для немед­

Ниже представлен простой пример приме­

swi tch.

11 Простой пример применения оператора switch
class SampleSwitch {
puЬlic static void main(String args[J)
for(int i=O; iO; n--)
System.out.println("тaкт



+

n);

Объявление переменных, управляющих циклом
Зачастую переменная, управляющая циклом

for,

for

требуется только для него

и нигде больше не используется. В таком случае переменную управления циклом
можно объявить в инициализирующей части оператора

for.

Например, преды-

146

Часть 1. Язык Java

дущую программу можно переписать, объявив управляющую переменную

int

в самом цикле

n

типа

for.

// Объявить переменную управления циклом
class ForTick {
puЫic static void main(String args[])
// здесь переменная n объявляется
for(int n=lO; n>O; n--)
System.out.println("тaкт " + n);

Объявляя переменную управления циклом

в

в

самом

самом

for

цикле

цикле

for

for

в самом цикле, не следует за­

бывать, что область и срок действия этой переменной полностью совпадают с об­
ластью видимости и сроком действия оператора цикла
ласть видимости переменной управления циклом
самого цикла. А за пределами цикла

for

f or

for.

Это означает, что об­

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

эта переменная прекращает свое сущес­

твование. Если же переменную управления циклом

for

требуется использовать

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

буется, большинство программирующих на
мом операторе цикла

for.

Java

for

нигде больше не тре­

предпочитают объявлять ее в са­

В качестве примера ниже приведена простая програм­

ма, в которой проверяется, является ли число простым. Обратите внимание на то,

что переменная

i управления циклом объявлена в самом цикле for, поскольку

она нигде больше не требуется.

// Проверить на простые числа
class FindPrime {
puЬlic static void main(String args[])
int num;
boolean isPrime;
num = 14;
if(num < 2) isPrime = false;
else isPrime
true;
for(int i=2; i