Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Язык программирования JAVA.pdf
Скачиваний:
373
Добавлен:
02.05.2014
Размер:
2.57 Mб
Скачать

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.