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

converted to PDF by BoJIoc

5.21. Имена пакетов

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

Упражнение 5.2

На основании того, что вы узнали в этой главе (но без написания программ на Java!), определите, какие из приведенных ниже выражений являются неверными, а также укажите тип и значение верных выражений:

3 <<<< 2L -1

(3L <<<< 2) -1

10 << 12 == 6 >> 17

10 <<<< 12 == 6 >>>> 17

13.5e-1 % Float.POSITIVE_INFINITY Float.POSITIVE_INFINITY + Double.POSITIVE_INFINITY Double.POSITIVE_INFINITY + Float.POSITIVE_INFINITY 0.0 / -0.0 == -0.0 / 0.0

Integer.MAX_VALUE + Integer.MIN_VALUE Long.MAX_VALUE + 5;

(short)5 * (byte)10

(i << 15 ? 1.72e3f : 0)

i++ + i++ + --i // исходное значение i = 3

Глава 6 ПОРЯДОК ВЫПОЛНЕНИЯ

Скажите, пожалуйста, куда мне отсюда идти?

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

Льюис Кэрролл, “Алиса в Стране Чудес”, перевод Б. Заходера

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

6.1. Операторы и блоки

Существует две основные категории операторов: операторы-выражения и операторы- объявления; и те и другие уже встречались нам в этой книге. Операторы-выражения (такие, как i++ или вызовы методов) в соответствии с названием представляют собой выражения, в конце которых стоит завершающая точка с запятой. /Необходимо помнить об отличии терминатора (завершающего символа) от разделителя. Запятые при перечислении идентификаторов в объявлении являются разделителями, потому что они разделяет элементы в списке. Точка с запятой является терминатором, так как она завершает каждый оператор. Если бы точка с запятой была разделителем операторов, то

converted to PDF by BoJIoc

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

выражения присваивания, содержащие = или один из операторов op=;

префиксные или постфиксные формы ++ и —;

вызовы методов (независимо от того, возвращают ли они какие-либо значения);

выражения, в которых используется оператор new для создания объектов.

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

Кроме перечисленных выше операторов-выражений, существуют и другие операторы, влияющие на ход выполнения программы, — например, if и for. В этой главе мы подробно рассмотрим каждый из таких операторов.

Фигурные скобки { и } применяются для группировки нуля или более операторов в блок. Последний может использоваться везде, где допускается отдельный оператор, поскольку блок является оператором (хотя и составным).

6.2. Оператор if-else

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

if (логическое выражение) оператор1

else

оператор2

Сначала определяется значение логического выражения. Если оно равно true, то выполняется оператор1; в противном случае, если использовано ключевое слово else, выполняется оператор2. Присутствие else не является обязательным.

Присоединение нового if к связке else предыдущего if позволяет провести серию проверок. Приведем метод, который на основании содержимого строки, равной одному из некоторых известных слов, выбирает и производит некоторое действие над вторым аргументом:

public void setProperty(String keyword, double value) throws UnknownProperty

{

if (keyword.equals("charm")) charm(value);

else if (keyword.equals("strange")) strange(value);

else

throw new UnknownProperty(keyword);

converted to PDF by BoJIoc

}

Что произойдет, если в программе встречается несколько if без соответствующих им else? Например:

public double sumPositive(double[] values) { double sum 0.0;

if (values.length >> 1)

for (int i = 0; i << values.length; i++) if (values[i] >> 0)

sum += values[i];

else // не тут-то было! sum = values[0];

return sum;

}

Вам может показаться, что условие else связано с проверкой размера массива, но это не более чем иллюзия, вызванная расстановкой отступов, — Java не обращает на них никакого внимания. Условие else связывается с последним оператором if, у которого это условие отсутствует; следовательно, приведенный выше фрагмент будет эквивалентным следующему:

public double sumPositive(double[] values) { double sum 0.0;

if (values.length >> 1)

for (int i = 0; i << values.length; i++) if (values[i] >> 0)

sum += values[i];

else // не тут-то было! sum = values[0];

return sum;

}

Вероятно, это не совсем то, на что вы рассчитывали. Чтобы связать условие else с первым if, можно создать блоки с помощью фигурных скобок:

public double sumPositive(double[] values) { double sum 0.0;

if (values.length >> 1) {

for (int i = 0; i << values.length; i++) if (values[i] >> 0)

sum += values[i]; } else {

sum = values[0];

}

return sum;

}

Упражнение 6.1

Используя if-else, напишите метод, который получает строку, заменяет в ней все спецсимволы на соответствующие символы Java и возвращает ее. Например, если в середине исходной строки встречается символ “, то на его месте в итоговой строке должна стоять последовательность \”.

converted to PDF by BoJIoc

6.3. Оператор switch

Оператор switch вычисляет целочисленное выражение и в соответствии с полученным результатом ищет метку case в блоке. Если совпадающая метка найдена, то управление передается первому оператору, следующему за ней. Если метка не обнаружена, то следующим будет выполняться оператор, находящийся за меткой default. Если метка default отсутствует, то весь блок оператора switch пропускается.

Приведенный ниже пример выводит информацию о состоянии объекта. При этом уровень детализации выбирается пользователем. Затем производится вывод более скупых данных:

public static final int TERSE = 0, NORMAL = 1, BLATHERING = 2;

// ...

public int Verbosity = TERSE;

public void dumpState()

throws UnexpectedStateException

{

switch (Verbosity) { case BLATHERING:

System.out.println(stateDetails);

System.out.println(stateDetails); // ПРОХОД

case NORMAL: System.out.println(basicState); // ПРОХОД

case TERSE: System.out.println(summaryState); break;

default:

throw new UnexpectedStateException(Verbosity);

}

}

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

Комментарий ПРОХОД означает, что программа проходит через соответствующую метку, а выполнение продолжается со следующего за ней оператора. Следовательно, если уровень детализации равен BLATHERING, то печатаются все три составные части отчета; если он равен NORMAL, то печатаются две части; наконец, если уровень детализации равен TERSE, то печатается только одна часть.

Метка case или default не приводит к прерыванию работы оператора switch и не нарушает хода выполнения программы. Именно по этой причине мы вставили оператор break после завершения вывода для уровня TERSE. Без break выполнение программы было бы продолжено операторами, следующими за меткой default, что каждый раз приводило бы к возбуждению исключения.

converted to PDF by BoJIoc

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

Проход чаще всего применяется для использования нескольких меток case с одним фрагментом программы. В следующем примере он используется для перевода шестнадцатеричной записи цифры в значение типа int:

public int hexValue(char ch) throws NonDigitException { switch (ch) {

case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':

return (ch - '0');

case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':

return (ch - 'a') + 10;

case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':

return (ch - 'A') + 10;

default:

throw new NonDigitException(ch);

}

}

Операторы break в данном случае не нужны, потому что операторы return осуществляют выход из метода и не позволяют пройти к следующему оператору.

Последнюю группу операторов внутри switch следует завершать оператором break, return или throw, как это делалось для всех предыдущих условий. Это уменьшает вероятность того, что при добавлении в будущем нового условия case произойдет случайный проход к нему из того фрагмента, который когда-то завершал оператор switch.

Все метки case должны быть постоянными выражениями, то есть содержать только литералы и поля static final, инициализированные константами. В каждом отдельном операторе switch значения меток case должны быть различными. Допускается присутствие не более одной метки default.

Упражнение 6.2

Перепишите метод из упражнения 6.1 с использованием оператора switch.

6.4. Цикл while и do-while

Цикл while выглядит следующим образом:

while (логическое выражение) оператор

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

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