Тема 4. Управляющая логика - BelyiZ/JavaCourses GitHub Wiki
Содержание:
Рассмотренные в прошлой теме операторы позволяют производить операции с данными (переменными). Но не менее часто в программе нам нужно контролировать в каком порядке, сколько раз, и будет ли вообще выполняться тот или иной блок кода. Например, у нас есть массив и мы хотим с каждым его элементом выполнить ряд одних и тех же операции. Или в зависимости от условия мы выполняем различные действия. Чтобы это стало возможным, в Java существуют операторы управления логикой программы (flow control).
Условный оператор if
Условный оператор if
позволяет собрать некоторые операции в единый блок и исполнять их только при выполнении
определенного условия. Например, нам необходимо написать такой код: если число четное, его нужно увеличить на единицу,
если нет - ничего с ним не делать. Тогда код будет выглядеть так:
int i = ...;
if (i % 2 == 0) {
i++;
}
Рассмотрим этот код подробнее. Сначала мы видим ключевое слово if
, затем в круглых скобках стоит выражение, результатом
которого является тип boolean
. После этого выражения идет блок с кодом в фигурных скобках. Условный оператор работает
следующим образом: если выражение возвращает true
, блок кода выполняется, иначе - нет.
Но иногда нам требуется выполнить какую-то другую логику если выражение вернуло нам false
. Для этого используется
ключевое слово else
. Посмотрим теперь на дополненную структуру условного оператора.
if (boolean-выражение) {
// выполнится если выражение возвращает true
} else {
// выполнится если выражение возвращает false
}
Для случаев, когда одной проверки не достаточно, и после получения false
от первого выражения, нужно проверить второе,
используется конструкция else if
:
if (выражение1) {
// выполнится если выражение1 возвращает true
} else if (выражение2) {
// выполнится если выражение1 возвращает false,
// а выражение2 - true
} else if (выражение3) {
// выполнится если выражение1 и выражение2 возвращают false,
// а выражение3 - true
} else {
// выполнится если выражение1, выражение2 и выражение3 возвращают false
}
Блоков else if
подряд может быть сколько угодно. А наличие в конце блока else
необязательно.
Все переменные объявленные внутри тела условного оператора доступны только там и не видны за его пределами.
Условный оператор switch
Иногда нам нужно выполнить различный код в зависимости от значения одной переменной. Можно использовать
последовательность из else if
для каждого из интересующих нас значений, но это не всегда удобно, да и читаться такой
код будет хуже.
Для подобных случаев в Java есть оператор switch
:
int a = ...;
switch(a) {
case 1:
// какой-то правильный код
break;
case 2:
// какой-то правильный код
break;
case 3:
case 5:
// какой-то правильный код
break;
default:
// какой-то правильный код
}
Мы инициализируем переменную и указываем что работать будем с ней, передав её в круглых скобках ключевому слову switch
.
Для каждого из нужных нам значений создаем блок case
. Внутри этого блока есть код, который будет выполняться только
в том случае, если переменная имеет значение указанное в этом блоке.
В конце каждого блока case
можно ставить ключевое слово break
. Оно прекратит выполнение всего оператора switch
.
Если этого не сделать, то автоматически начнет выполняться код следующего блока case
или default
, и так будет до тех
пор, пока не выполнится весь switch
или не будет выполнен оператор break
.
Если ни одно из значений, указанных в блоках case
, не соответствует реальному значению переменной - выполняется код
написанный в блоке default
. Логики по умолчанию может и не быть - ключевое слово default
необязательно использовать
в блоке switch
.
Обратим внимание, что switch
работает только с некоторыми типами данных:
- целочисленные примитивы
byte
,short
,char
иint
; - классы-обертки для этих примитивов (
Character
,Byte
,Short
, иInteger
); enum
-перечисления (будем рассматривать в следующих темах);String
.
Циклы
Циклы используются для повторения выполнения одного и того же блока кода несколько раз подряд. Это очень полезно,
например, когда мы работаем с массивами. В Java существует четыре вида циклов: for
, for-each
, while
, do-while
.
Они отличаются логикой поведения и предназначаются для разных ситуаций.
Одно повторение блока операций внутри цикла называется итерацией. Сам блок кода - телом цикла.
Цикл for
Используется для повторения блока кода указанное количество раз. Рассмотрим синтаксис циклов for
:
for (выражение1; выражение2; выражение3) {
// блок кода, который будет выполняться несколько раз
}
Здесь выражение1
- любое выражение, которое будет выполнено один раз при инициализации цикла, еще до первой
итерации (обычно это объявление переменной);
выражение2
- boolean
-выражение, которое выполняется перед каждой итерацией, если выражение возвращает true
, итерация
выполняется, если false
- выполнение всего цикла прекращается;
выражение3
- любое выражение, которое выполняется по окончанию каждой итерации.
Рассмотрим пример, в котором мы хотим выполнить определенные операции 4 раза:
for(int i = 0; i < 4; i++) {
// тело цикла
}
В первую очередь выполняется выражение int i = 0;
, инициализируется целочисленная переменная "i" равная нулю. Затем
выполняется проверка i < 5;
, которое вернет true
. Выполнится первая итерация цикла и завершится она выражением i++
, что увеличит значение заведенной ранее переменной на единицу.
Затем все повторится еще раз, только теперь с другим значением переменной "i". Так будет повторяться до тех пор, пока
значение не увеличится до 5 и выражение i < 5;
не вернет false
. Тогда цикл завершит свое выполнение.
Переменные, созданные во время инициализации цикла, доступны коду в его теле, но не видны за его пределами. То же самое относится и к переменным, объявленным в самом теле цикла.
int a = 0;
for(int b=0; b<5; b++) {
a += b;
int c = a * b;
// b и c доступны
}
// b и c недоступны
Цикл for-each
Не менее популярным вариантом цикла в Java является for-each
. Его основная задача выполнять определенный набор
операций с каждым из элементов массива данных. Это может быть простой массив, одна из коллекций (будем изучать позже)
или любой класс, реализующий интерфейс Iterable
(значения этих страшных слов ждут нас впереди).
Рассмотрим пример:
String[] names = new String[] {"Коля", "Оля", "Ваня", "Аня", "Кира", "Ира", "Валя", "Аля"};
for (String name : names) {
// тело цикла
}
Тут мы хотим выполнить операции из тела цикла с каждым именем из массива. Главным отличием от обычного цикла for
является отсутствие каких-либо выражений в круглых скобках после ключевого слова for
. После двоеточия указывается
переменная, значения которой будут перебираться. Слева же от двоеточия объявляется переменная, которая будет доступна в
теле цикла. При каждой новой итерации она будет заполняться следующим значением из массива данных.
Во время выполнения цикла будет сделано столько итераций, сколько элементов находится в массиве данных.
Циклы while и do-while
Немного отличается по синтаксису от предыдущих вариантов цикл while
. Главное его предназначение - выполнять новые
итерации до тех пор, пока истинно переданное в него boolean
-выражение.
Если посмотреть на синтаксис:
while (выражение) {
// тело цикла
}
таким образом видно, что нет никаких объявлений переменных, как это было в ранее рассматриваемых примерах. В скобках выражение,
возвращающее boolean
.
Перед каждой итерацией выполняется выражение
, если оно возвращает true
- цикл продолжает работу, если false
-
завершается.
Цикл do-while
устроен похожим образом, но проверка выполнятся не до итерации, а после:
do {
// тело цикла
} while (выражение);
То есть этот вариант позволяет выполнить одну итерацию цикла даже если условное выражение ложно.
Как и в остальных циклах, переменные, объявленные внутри цикла, доступны только в рамках его тела.
Операторы break и continue
Нередко случаются ситуации, когда нужно экстренно завершить выполнение итерации или всего цикла. На помощь в таких
случаях приходят операторы break
и continue
.
Оператор continue
принудительно завершает текущую итерацию цикла. Несмотря на это, все необходимые пост-итеративные
операции и проверки будут выполнены. Затем начнется новая итерация, если это возможно. Это ключевое слово может быть
использовано, когда в итерируемом массиве есть данные, которые нужно пропустить.
Оператор break
завершает выполнение всего цикла. При этом никакие пост-итеративные операции и проверки не будут
выполнены.
Оба этих ключевых слова работают со всеми вариантами циклов в Java.
// ищем Ваню
String[] names = new String[] {"Коля", "Оля", "Ваня", "Аня", "Кира", "Ира", "Валя", "Аля"};
boolean vanyaFound = false;
for (String name : names) {
if (name.equals("Ваня") {
vanyaFound = true; // Нашелся!
break; // нет нужды крутить цикл дальше
}
}
Список литературы/курсов
- https://proproprogs.ru/java_base/java-uslovnye-operatory-if-i-switch
- https://vertex-academy.com/tutorials/ru/vetvlenie-v-java/
- https://javarush.ru/groups/posts/cikly-java
- https://skillbox.ru/media/base/kak-ispolzovat-tsikly-v-yazyke-java-polnoe-rukovodstvo/
Тема 3. Операторы в Java | Оглавление | Тема 5. Работа со строками