Ключевой момент: пропуск необходимых фигурных скобок, завершение инструкции if в неправильном месте, перепутывание == и =, а также двусмысленность конструкций else являются частыми ошибками в инструкциях выбора. Дублированные выражения в инструкциях if-else и проверка равенства двойных величин являются распространёнными подводными камнями.
Следующие ошибки распространены среди начинающих программистов.
Частая ошибка 1: Пропуск необходимых фигурных скобок
Фигурные скобки могут быть пропущены если блок содержит одну инструкцию. Тем не менее, забывание фигурных скобок, когда они необходимы для группирования нескольких инструкций, является распространённой ошибкой программирования. Если вы изменили код, добавив новые инструкции в выражение if без фигурных скобок, вы должны вставить фигурные скобки. Например, следующий код в (a) является неверным. Он должен быть переписан с использованием фигурных скобок для группирования нескольких инструкций, как это показано в (b):
Частая ошибка 2: Неверное использование точки с запятой в строке if
Добавление точки с запятой в строку if, как это показано ниже в (a), является частой ошибкой:
Ошибку трудно найти, поскольку она не является ни ошибкой компилирования, ни ошибкой во время выполнения; это логическая ошибка. Код (a) эквивалентен коду (b) с пустым блоком.
Эта ошибка часто случается, когда вы используете стиль блоков «на следующей строке». Использование стиля блоков «на конце строки» может помочь избежать эту ошибку.
Частая ошибка 3: Избыточное тестирование булевых значений
При тестировании boolean значения на true или false использование оператора проверки равенства, как это сделано в коде (a), является избыточным:
Вместо этого лучше напрямую тестировать величину Boolean, как показано в (b). Другой хорошей причиной делать это является избежание ошибок, которые трудно обнаружить. Использование оператора = вместо оператора == для сравнения равенства двух элементов в проверяемом условии является частой ошибкой. Это может привести к следующему ошибочному выражению:
if (even = true) System.out.println("It is even.");
Это выражение не вызывает ошибок компиляции. Оно присваивает even значение true, поэтому even всегда является true.
Частая ошибка 4: Неоднозначность else
Ниже код в (a) имеет два пункта if и один пункт else. Какой пункт if связан с пунктом else? Отступы указывают, что пункт else связан с первым пунктом if.
Тем не менее, пункт else на самом деле связан со вторым пунктом if. Эта ситуация известна как неоднозначность else. Пункт else всегда связан с самым недавним незанятым пунктом if в том же блоке. Поэтому выражение в (a) является эквивалентом кода в (b).
Поскольку (i > j) является ложью, в выражениях (a) и (b) ничего не будет выведено. Чтобы принудительно привязать пункт else к первому пункту if, вы должны добавить пару фигурных скобок:
int i = 1, j = 2, k = 3; if (i > j) { if (i > k) System.out.println("A"); } else System.out.println("B");
Это выражение отобразит B.
Частая ошибка 5: Проверка равенства двух значений с плавающей запятой
Как обсуждалось в «Частая ошибка 3: Ошибки округления» предыдущей главы, числа с плавающей запятой имеют ограниченную точность; при использовании чисел с плавающей запятой могут возникать ошибки округления. Таким образом, проверка равенства двух значений с плавающей запятой не является надежной. Например, вы ожидаете, что следующий код отобразит true, но на удивление он отображает false.
double x = 1.0 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1; System.out.println(x == 0.5);
Здесь, x не является точно 0.5, он равен 0.5000000000000001. Вы не можете надежно проверить равенство двух значений с плавающей запятой. Тем не менее, вы можете сравнить, насколько они достаточно близки, проверяя, отличается ли разница двух чисел от некоторого порогового значения. То есть два числа x и y очень близки, если | x-y | < ε для очень малого значения ε. ε – это греческая буква, называется эпсилон, обычно используется для обозначения очень маленького значения. Обычно вы устанавливаете ε в 10-14 для сравнения двух значений типа double и 10-7 для сравнения двух значений типа float. Например, следующий код
final double EPSILON = 1E-14; double x = 1.0 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1; if (Math.abs(x - 0.5) < EPSILON) System.out.println(x + " это примерно 0.5");
отобразит
0.5000000000000001 это примерно 0.5
Для возвращения абсолютного значения a может использоваться метод Math.abs(a).
Распространённый подводный камень 1: Упрощение присваивания булевой переменной
Часто начинающие программисты пишут код, который присваивает тестовое условие переменной boolean примерно как в коде (a):
Это не ошибка, но лучше записывать так, как показано в (b).
Распространённый подводный камень 2: Различные случаи дублирования кода
Часто начинающие программисты в различных ситуациях пишут дублирующий код, который мог бы быть скомбинирован в одном месте. Например, в следующем коде строка System.out.println("The tuition is " + tuition); является дублированной:
if (inState) { tuition = 5000; System.out.println("The tuition is " + tuition); } else { tuition = 15000; System.out.println("The tuition is " + tuition); }
Это не ошибка, но следовало бы записать так:
if (inState) { tuition = 5000; } else { tuition = 15000; } System.out.println("The tuition is " + tuition);
Новый код устроняет дублирование и упрощает поддержку кода, поскольку если понадобиться изменить инструкцию print, то достаточно изменить только в одном месте.
Проверь себя:
- Какие из следующих утверждений эквивалентны? В каких из них правильно расставлены отступы?
- Перепишите следующие инструкции, используя булево выражение:
if (count % 10 == 0) newLine = true; else newLine = false;
- Правильны ли следующие выражения? Какое из них лучше?
- Какой вывод будет у следующего кода, если number равно 14, 15 или 30?
Отличный "Учебник: программирование на Java"! Все написано доступным языком, с примерами и заданиями по пройденному материалу. Советую всем, начинающим изучение языка Java.
Ну и ждем продолжения конечно-же!!!