Главная » Java » Оператор for

0

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

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;

}

В данном случае в цикле одновременно изменяются две переменные: показатель степени (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

{

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;

// …  обработка лексемы …

}

Оператор 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.

Глава 7

ИСКЛЮЧЕНИЯ

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

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

Журнал PS армии США,

август 1993 года

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

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

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

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

Исключение возбуждается, когда возникает неожиданное ошибочное состояние. Затем исключение перехватывается соответствующим  условием в стеке вызова методов. Если исключение не перехвачено, срабатывает обработчик исключения по умолчанию, который обычно выводит полезную информацию об исключении (скажем, содержимое стека вызовов).

Источник: Арнольд К., Гослинг Д. – Язык программирования Java (1997)

По теме:

  • Комментарии