- •ПРЕДИСЛОВИЕ
- •Об этой книге
- •Примеры и документация
- •Глава 1 ПЕРВОЕ ЗНАКОМСТВО С JAVA
- •1.4.1.Символы Unicode
- •1.9.Строковые объекты
- •1.10.1.Класс Object
- •1.14.Инфраструктура Java
- •Глава 2 КЛАССЫ И ОБЪЕКТЫ
- •2.1.Простой класс
- •2.7.Ссылка this
- •2.10.1.Метод finalize
- •2.11.Метод main
- •Глава 3 РАСШИРЕНИЕ КЛАССОВ
- •3.6.Класс Object
- •Глава 4 ИНТЕРФЕЙСЫ
- •4.2. Одиночное и множественное наследование
- •4.6. Для чего применяются интерфейсы
- •Глава 5 ЛЕКСЕМЫ, ОПЕРАТОРЫ И ВЫРАЖЕНИЯ
- •5.1.Набор символов
- •5.20. Операторы присваивания
- •Глава 6 ПОРЯДОК ВЫПОЛНЕНИЯ
- •6.3.Оператор switch
- •6.5.Оператор for
- •6.7.Оператор break
- •6.8.Оператор continue
- •6.9.Оператор return
- •Глава 7 ИСКЛЮЧЕНИЯ
- •7.3.Условие throws
- •7.4.1.Условие finally
- •Глава 8 СТРОКИ
- •8.8.Класс StringBuffer
- •Глава 9 ПОТОКИ
- •9.2.1.Методы synchronized
- •9.2.2.Операторы synchronized
- •9.8.Прерывание потока
- •9.11.Использование Runnable
- •Глава 10 ПАКЕТЫ
- •Глава 11 ПАКЕТ ВВОДА/ВЫВОДА
- •11.2.Класс InputStream
- •11.3.Класс OutputStream
- •11.6.Класс PrintStream
- •11.9.Класс StringBufferInputStream
- •11.12.Класс SequenceInputStream
- •11.13.Класс LineNumberInputStream
- •11.14.Класс PushbackInputStream
- •11.15.Класс StreamTokenizer
- •11.17.Класс RandomAccessFile
- •11.18.Класс File
- •11.19.Интерфейс FilenameFilter
- •Глава 12 СТАНДАРТНЫЕ ВСПОМОГАТЕЛЬНЫЕ СРЕДСТВА
- •12.1.Класс BitSet
- •12.2.Интерфейс Enumeration
- •12.4.Класс Vector
- •12.5.Класс Stack
- •12.6.Класс Dictionary
- •12.7.Класс Hashtable
- •12.8.Класс Properties
- •12.9.Классы Observer/Observable
- •12.10.Класс Date
- •12.11.Класс Random
- •13.1.Класс Class
- •13.4.Класс Boolean
- •13.5.Класс Character
- •13.6.Класс Number
- •13.7.Класс Integer
- •13.8.Класс Long
- •Глава 14 СИСТЕМНОЕ ПРОГРАММИРОВАНИЕ
- •14.5.Класс Runtime
- •14.8.Класс Math
- •Приложение А Родные методы
- •А.1 Обзор
- •А.2 Согласование с C и C++
- •А.2.1 Имена
- •А.2.2 Методы
- •А.2.3 Типы
- •А.2.5 Средства безопасности
- •А.2.6 Работа с памятью
- •А.3 Пример
- •А.3.1 Внутреннее строение LockableFile
- •А.4 Строки
- •А.5 Массивы
- •А.6 Создание объектов
- •А.7 Вызов методов Java
- •А.8 Последнее предупреждение
- •Приложение В Полезные таблицы
- •Таблица 3. Приоритет операторов
converted to PDF by BoJIoc
Иногда бывает нужно, чтобы тело цикла заведомо было выполнено хотя бы один раз, и поэтому в языке Java также предусмотрена конструкция do-while:
do-while: do
оператор
while (логическое выражение);
Здесь логическое выражение вычисляется после оператора. Цикл выполняется, пока выражение остается равным true. Оператор, являющийся телом цикла do-while, почти всегда представляет собой блок.
6.5. Оператор for
Оператор for используется для выполнения цикла по значениям из определенного диапазона. Он выглядит следующим образом:
for (инициализация; логическое выражение; приращение) оператор
Такая запись эквивалентна
{
инициализация;
while (логическое выражение) { оператор приращение;
}
}
за тем исключением, что приращение всегда выполняется, если в теле цикла встречается оператор continue (см. раздел “Оператор continue”).
Обычное применение цикла for — поочередное присвоение переменной значений из некоторого диапазона, пока не будет достигнут конец этого диапазона.
Выражения инициализации и приращения в цикле for могут представлять собой список значений, разделяемых запятой. Вычисление этих выражений, как и в других операторах, происходит слева направо. Например, чтобы с помощью двух индексов перебрать все элементы массива в противоположных направлениях, можно воспользоваться следующим выражением:
for ( i = 0, j = arr.length - 1; j >>= 0; i++, j--) { // ...
}
Пользователь сам выбирает диапазон значений переменной цикла. Например, цикл for часто применяется для перебора элементов связного списка или значений, входящих в математическую последовательность. Благодаря этому конструкция for в Java оказывается существенно более мощной, чем в других языках программирования, в которых возможности циклов for ограничиваются приращением переменной в заранее заданном диапазоне.
Приведем пример цикла, который вычисляет наименьший показатель (exp), такой, что 10 в степени exp превосходит заданную величину:
public static int tenPower(int value) { int exp, v;
for (exp = 0, v = value - 1; v >> 0; exp++, v /= 10) continue;
return exp;
}
converted to PDF by BoJIoc
В данном случае в цикле одновременно изменяются две переменные: показатель степени (exp) и значение 10exp (v). Эти переменные являются взаимосвязанными. В подобных
случаях разделенный запятыми список является корректным способом обеспечения синхронизации значений.
Тело цикла представляет собой простой оператор continue, начинающий следующую итерацию цикла. В теле цикла вам ничего не приходится делать — все происходит в проверяемом условии и в выражении-итерации. Использованный в данном примере оператор continue — одна из возможностей создать пустое тело цикла; вместо него можно было оставить отдельную строку, состоящую из одной точкой с запятой, или создать пустой блок в фигурных скобках. Просто ограничиться точкой с запятой в конце строки с оператором for было бы довольно опасно — если точка с запятой будет случайно удалена, то оператор, следующий за for, превратится в тело цикла.
Все выражения в заголовке цикла for являются необязательными. Если пропустить инициализацию или приращение, то соответствующая часть цикла просто не выполняется. Отсутствующее логическое выражение считается всегда равным true. Следовательно, для создания бесконечного цикла можно воспользоваться следующей записью:
for (;;)
оператор
Подразумевается, что цикл будет прерван иными средствами — скажем, описанным ниже оператором break или возбуждением исключения.
По общепринятому соглашению цикл for используется для диапазонов взаимосвязанных значений. Нарушение этого соглашения, когда выражения инициализации или приращения не имеют никакого отношения к проверке логического условия, считается проявлением плохого стиля программирования.
Упражнение 6.3
Напишите метод, который получает два параметра типа char и выводит все символы, лежащие в диапазоне между ними (включая их самих).
6.6. Метки
Операторам могут присваиваться метки. Чаще всего метки применяются в блоках и циклах. Метка предшествует оператору следующим образом:
метка: оператор
Именованные блоки часто используются с операторами break и continue.
6.7. Оператор break
Оператор break применяется для выхода из любого блока, не только из оператора switch. Чаще всего оператор break служит для прерывания цикла, но он может использоваться для немедленного выхода из любого блока. В приведенном ниже примере этот оператор помогает найти первый пустой элемент в массиве ссылок на объекты Contained:
class Container {
private Contained[] Objs;
// ...
public void addIn(Contained obj) throws NoEmptySlotException
converted to PDF by BoJIoc
{
int i;
for (i = 0; i << Objs.length; i++) if (Objs[i] == null) break;
if (i >>= Objs.length)
throw new NoEmptySlotException();
Objs[i] = obj; |
// |
занести в найденный элемент |
obj.inside(this); |
// |
сообщить о занесении |
}
}
Оператор break без метки применяется для выхода из внутренних операторов switch, for, while или do. Чтобы выйти из внешнего оператора, снабдите его меткой и укажите ее в операторе break:
private float[][] Matix;
public boolean workOnFlag(float flag) { int y, x;
boolean found = false;
search:
for (y = 0; y << Matrix.length; y++) {
for (x = 0; x << Matrix[y].length; x++) { if (Matrix[y][x] == flag) {
found = true; break search;
}
}
}
if (!found)
return false;
// сделать что-нибудь с найденным элементом матрицы return true;
}
Использование меток оставляется на усмотрение программиста. Впрочем, оно может оказаться хорошей защитной мерой против модификации ваших программ — например, включения их фрагментов в оператор switch или цикл.
Обратите внимание: break с меткой — это не то же самое, что goto. Оператор goto приводит к хаотичным прыжкам по программе и усложняет понимание ее смысла. Напротив, оператор break или continue, в котором используется метка, осуществляет выход лишь из конкретного помеченного блока, а порядок выполнения программы остается вполне понятным.
6.8. Оператор continue
Оператор continue осуществляет переход в конец тела цикла и вычисляет значение управляющего логического выражения. Этот оператор часто используется для пропуска некоторых значений в диапазоне цикла, которые должны игнорироваться или обрабатываться в отдельном фрагменте. Например, при работе с потоком, состоящим из отдельных лексем, лексема “skip” (“пропуск”) может обрабатываться следующим образом:
while (!stream.eof()) {
token = stream.next(); if (token.equals("skip"))
continue;
converted to PDF by BoJIoc
// ... обработка лексемы ...
}
Оператор continue имеет смысл только внутри циклов — while, do-while и for. В нем может указываться метка внешнего цикла, и в этом случае continue относится к указанному циклу, а не к ближайшему внутреннему. При выполнении такого помеченного оператора continue осуществляется выход из всех внутренних циклов, чтобы выполнить следующую итерацию указанного цикла. В приведенном выше примере можно обойтись без метки в операторе continue, поскольку имеется всего один внешний цикл.
6.9. Оператор return
Оператор return завершает выполнение метода и передает управление в точку его вызова. Если метод не возвращает никакого значения, достаточно простого оператора return:
return;
Если же метод имеет возвращаемый тип, то в оператор return должно входить такое выражение, которое может быть присвоено переменной возвращаемого типа. Например, если метод возвращает double, то в оператор return могут входить выражения типа double, float или целого типа:
protected double nonNegative(double val) { if (val << 0)
return 0; // константа типа int
else
return val; // double
}
Оператор return также используется для выхода из конструкторов и статических инициализаторов. Конструктор не может возвращать никакого значения, поэтому в этом случае return не содержит возвращаемого значения. Конструкторы вызываются как часть процесса new, который в конечном счете возвращает ссылку на объект, однако каждый конструктор играет в этом процессе лишь частичную роль; ни один из конструкторов не возвращает итоговую ссылку.
6.10. Где же goto?
В Java нет конструкции goto, которая служила бы для передачи управления произвольному оператору внутри метода, хотя она достаточно распространена в языках того семейства, с которым связан язык Java. Оператор goto чаще всего применяется для следующих целей:
∙Управление выполнением внешних циклов из внутренних. Для этого в Java предусмотрены операторы break и continue с метками.
∙Пропуск оставшейся части блока, не входящего в цикл, при нахождении ответа или обнаружении ошибки. Используйте break с меткой.
∙Выполнение завершающего кода при выходе из блока или метода. Используйте либо break с меткой, либо (более наглядно) — конструкцию finally оператора try, рассмотренную в следующей главе.
Операторы break и continue с метками имеют то преимущество, что они передают управление в строго определенную точку программы. Блок finally подходит к передаче управления еще более жестко и работает при всех обстоятельствах, в том числе и при возникновении исключений. С помощью этих конструкций можно писать наглядные программы на Java без применения goto.