17

17


Совмещенное присваивание не требует приведения для типов char, byte и short, хотя для них и производится повышение, как и в случае с арифметиче¬скими операциями. С другой стороны, отсутствие приведения в таких случаях, несомненно, упрощает программу.
Можно легко заметить, что за исключением типа boolean, любой примитив¬ный тип может быть преобразован к другому примитиву. Как упоминалось ра¬нее, необходимо остерегаться сужающего приведения при преобразованиях к меньшему типу, так как при этом возникает риск потери информации.
Резюме
Читатели с опытом работы на любом языке семейства С могли убедиться, что операторы Java почти нйчем не отличаются от классических. Если же материал этой главы показался трудным, обращайтесь к мультимедийной презентации «Thinking in С» (www.MindView.net).


Управляющие конструкции

П
одобно любому живому существу, программа должна управлять своим миром и принимать решения во время исполнения. В языке Java для принятия решений используются управляющие конструкции.
В Java задействованы все управляющие конструкции языка С, поэтому чита¬телям с опытом программирования на языке С или С++ основная часть мате¬риала будет знакома. Почти во всех процедурных языках поддерживаются стандартные команды управления, и во многих языках они совпадают. В Java к их числу относятся ключевые слова if-else, while, do-while, for, а также команда выбора switch. Однако в Java не поддерживается часто критикуемый оператор goto (который, впрочем, все же является самым компактным решением в неко¬торых ситуациях). Безусловные переходы «в стиле» goto возможны, но гораздо более ограничены по сравнению с классическими переходами goto.
true и false

Все конструкции с условием вычисляют истинность или ложность условного выражения, чтобы определить способ выполнения. Пример условного выраже¬ния — А — В. Оператор сравнения = проверяет, равно ли значение А значению В. Результат проверки может быть истинным (true) или ложным (false). Любой из описанных в этой главе операторов сравнения может применяться в условном выражении. Заметьте, что Java не разрешает использовать числа в качестве ло¬гических значений, хотя это позволено в С и С++ (где не-ноль считается «ис¬тинным», а ноль — «ложным»). Если вам потребуется использовать числовой тип там, где требуется boolean (скажем, в условии if(a)), сначала придется его преобразовать к логическому типу оператором сравнения в условном выраже¬нии — например, if (а != 0).
if-else
Команда if-else является, наверное, наиболее распространенным способом пере¬дачи управления в программе. Присутствие ключевого слова else не обязатель¬но, поэтому конструкция if существует в двух формах:
if(логическое выражение) команда
и
if(логическое выражение) команда
else
команда
Условие должно дать результат типа boolean. В секции команда располагает¬ся либо простая команда, завершенная точкой с запятой, либо составная конст¬рукция из команд, заключенная в фигурные скобки.
В качестве примера применения if-else представлен метод test(), который вы¬дает информацию об отношениях между двумя числами — «больше», «меньше» или «равно»:
//. control/IfElse.java
import static net.mindview.util.Print.*;
public class IfElse {
static int result = 0; static void test(int testval. int target) { if(testval > target) result = +1; else if(testval < target) result = -1:
else
result = 0; // равные числа
}
public static void main(String[] args) { test(10. 5); print(result); test(5. 10); print(result); test(5. 5); print(result);
}
} /* Output:
1
-1
0
Внутри метода test() встречается конструкция else if; это не новое ключевое слово, a else, за которым следует начало другой команды — if.
Java, как и С с С++, относится к языкам со свободным форматом. Тем не ме¬нее в командах управления рекомендуется делать отступы, благодаря чему чи¬тателю программы будет легче понять, где начинается и заканчивается управ¬ляющая конструкция.

Управляющие конструкции
Циклы
Конструкции while, do-while и for управляют циклами и иногда называются цик¬лическими командами. Команда повторяется до тех пор, пока управляющее логи¬ческое выражение не станет ложным. Форма цикла while следующая:
\л/ИПе(логическое выражение) команда
логическое выражение вычисляется перед началом цикла, а затем каждый раз пе¬ред выполнением очередного повторения оператора.
Следующий простой пример генерирует случайные числа до тех пор, пока не будет выполнено определенное условие:
//: control/WhileTest java // Пример использования цикла while
public class WhileTest {
static boolean conditionO {
boolean result = Math.randomO < 0.99; System.out.print(result + "); return result;
}
public static void main(String[] args) { while(conditionO)
System out printlnC"Inside 'while"'), System.out.println("Exited 'while'");
}
} /* (Выполните, чтобы просмотреть результат) *///•-
В примере используется статический метод random() из библиотеки Math, ко¬торый генерирует значение double, находящееся между 0 и 1 (включая 0, но не 1). Условие while означает: «повторять, пока condition() возвращает true». При каж¬дом запуске программы будет выводиться различное количество чисел.
do-while
Форма конструкции do-while такова:
do
команда
и/1гЛе(логическое выражение);
Единственное отличие цикла do-while от while состоит в том, что цикл do- while выполняется по крайней мере единожды, даже если условие изначально ложно. В цикле while, если условие изначально ложно, тело цикла никогда не от¬рабатывает. На практике конструкция do-while употребляется реже, чем while.
for
103
Пожалуй, конструкции for составляют наиболее распространенную разновид¬ность циклов. Цикл for проводит инициализацию перед первым шагом цикла. Затем выполняется проверка условия цикла, и в конце каждой итерации
осуществляется некое «приращение» (обычно изменение управляющей пере¬менной). Цикл for записывается следующим образом:
^(инициализация; логическое выражение; шаг)
команда
Любое из трех выражений цикла (инициализация, логическое выражение или шаг) можно пропустить. Перед выполнением каждого шага цикла проверяется условие цикла; если оно окажется ложно, выполнение продолжается с инструк¬ции, следующей за конструкцией for. В конце каждой итерации выполняется секция шаг.
Цикл for обычно используется для «счетных» задач:
// control/ListCharacters.java
// Пример использования цикла "for": перебор
// всех ASCII-символов нижнего регистра
public class ListCharacters {
public static void main(String[] args) { for(char с = 0, с < 128, С++)
i f(Character.i sLowerCase(c))
System out рппШСзначение- " + (int)c + " символ. " + с).
}
} /* Output- значение 97 символ a значение 98 символ b" значение 99 символ с" значение 100 символ d" значение- 101 символ: е" значение 102 символ, f" значение 103 символ, д" значение 104 символ: h" значение- 105 символ- i значение 106 символ- j
*///:-
Обратите внимание, что переменная i определяется в точке ее использова¬ния, в управляющем выражении цикла for, а не в начале блока, обозначенного фигурными скобками. Область действия для i — все выражения, принадлежа¬щие циклу.
В программе также используется класс-«обертка» java.Lang.Character, кото¬рый не только позволяет представить простейший тип char в виде объекта, но и содержит ряд дополнительных возможностей. В нашем примере используется статический метод этого класса isLowerCase(), который проверяет, является ли некоторая буква строчной.
Традиционные процедурные языки (такие, как С) требовали, чтобы все пе¬ременные определялись в начале блока цикла, чтобы компилятор при создании блока мог выделить память под эти переменные. В Java и С++ переменные раз¬решено объявлять в том месте блока цикла, где это необходимо. Это позволяет программировать в более удобном стиле и упрощает понимание кода.
Оператор-запятая
Ранее в этой главе уже упоминалось о том, что оператор «запятая» (но не запя- тая-разделитель, которая разграничивает определения и аргументы функций) может использоваться в Java только в управляющем выражении цикла for. И в секции инициализации цикла, и в его управляющем выражении можно за¬писать несколько команд, разделенных запятыми; они будут обработаны после¬довательно.
Оператор «запятая» позволяет определить несколько переменных в цикле for, но все эти переменные должны принадлежать к одному типу:
//. control/CommaOperator.java
public class CommaOperator {
public static void main(String[] args) {
for(int i = 1. j = i + 10, i < 5. i++, j = i * 2) {
System out.printlnC'i = " + i + " j = " + j);
}
}
} /* Output: i = 1 j = 11 i = 2 j = 4 i = 3 j = 6 i = 4 j = 8 *///:-
Определение int в заголовке for относится как к i, так и к j. Инициализацон- ная часть может содержать любое количество определений переменных одного типа. Определение переменных в управляющих выражениях возможно только в цикле for. На другие команды выбора или циклов этот подход не распростра¬няется.
Синтаксис foreach
В Java SE5 появилась новая, более компактная форма for для перебора элемен¬тов массивов и контейнеров (см. далее). Эта упрощенная форма, называемая синтаксисом foreach, не требует ручного изменения служебной переменной для перебора последовательности объектов — цикл автоматически представляет очередной элемент.
Следующая программа создает массив float, после чего перебирает все его элементы:
//• control/ForEachFloat.java import java util.*,
public class ForEachFloat {
public static void main(String[] args) { Random rand = new Random(47), float f[] = new float[10], for(int i = 0; i < 10. i++)
f[i] = rand.nextFloatO, for(float x f)
System out println(x).
}
} /* Output
0.72711575
0.39982635
0.5309454
0.0534122
0.16020656
0.57799757
0.18847865
0.4170137
0.51660204
0.73734957 *///.-
Массив заполняется уже знакомым циклом for, потому что для его заполне¬ния должны использоваться индексы. Упрощенный синтаксис используется в следующей команде:
for(float X f)
Эта конструкция определяет переменную х типа float, после чего последова¬тельно присваивает ей элементы f.
Любой метод, возвращающий массив, может использоваться с данной разно¬видностью for. Например, класс String содержит метод toCharArray(), возвращаю¬щий массив char; следовательно, перебор символов строки может осуществлять¬ся так:
//: control/ForEachString.java
public class ForEachString {
public static void main(String[] args) {
for(char с : "An African Swallow".toCharArray() ) System.out.print(c + " ");
}
} /* Output:
An African Swallow *///.-
Как будет показано далее, «синтаксис foreach» также работает для любого объекта, поддерживающего интерфейс Iterable.
Многие команды for основаны на переборе серии целочисленных значений:
for (int i = 0; i < 100; i++)
В таких случаях «синтаксис foreach» работать не будет, если только вы пред¬варительно не создадите массив int. Для упрощения этой задачи я включил в библиотеку net.mindview.util.Range метод range(), который автоматически гене¬рирует соответствующий массив:
//: control/ForEachlnt.java

Report Page