Java: Отрицание

Наряду с логическими операторами И и ИЛИ часто используется операция "отрицание". Она меняет логическое значение на противоположное. В Java отрицанию соответствует унарный оператор !:

System.out.println(!true);  // => false
System.out.println(!false); // => true

Если есть метод, проверяющий четность числа, то с помощью отрицания можно выполнить проверку нечетности:

public static boolean isEven(int number) {
    return number % 2 == 0;
}

System.out.println(App.isEven(10));  // => true
System.out.println(!App.isEven(10)); // => false

В примере выше мы добавили ! слева от вызова метода и получили обратное действие. Отрицание позволяет выражать задуманные правила в коде без написания новых методов.

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

System.out.println(!(5 == 5 || 5 == 3)); // => false

// Это же выражение можно записать и по-другому,
// "число не равно 5 и не равно 3"
System.out.println(5 != 5 && 5 != 3);    // => false

Двойное отрицание

Отрицание разрешается ставить несколько раз подряд. В логике двойное отрицание равносильно отсутствию отрицания:

System.out.println(!!true);  // => true
System.out.println(!!false); // => false

System.out.println(!!App.isEven(10)); // => true
System.out.println(!!App.isEven(11)); // => false

Приоритет

Оператор ! можно комбинировать с && и ||. Среди логических операторов у отрицания наивысший приоритет, поэтому оно применяется первым:

// (!true) || true  =>  false || true  =>  true
System.out.println(!true || true);     // => true

// (!true) && false  =>  false && false  =>  false
System.out.println(!true && false);    // => false

Скобки меняют порядок вычисления, и ! применяется уже к результату внутри них:

// !(true || true)  =>  !true  =>  false
System.out.println(!(true || true));   // => false

// !(true && false)  =>  !false  =>  true
System.out.println(!(true && false));  // => true

Практический пример. Метод проверяет, может ли водитель сесть за руль. Нужны права и трезвость, поэтому второе условие проходит через отрицание:

public static boolean canDrive(boolean hasLicense, boolean isDrunk) {
    return hasLicense && !isDrunk;
}

System.out.println(App.canDrive(true, false));  // => true  (есть права, трезвый)
System.out.println(App.canDrive(true, true));   // => false (есть права, но пьяный)
System.out.println(App.canDrive(false, false)); // => false (нет прав)

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

Законы де Моргана

При работе со сложными логическими выражениями бывает нужно их инвертировать или переписать в равносильную форму, которую удобнее читать. Для этого существуют законы де Моргана, два правила, которые описывают, как отрицание распределяется по составному выражению:

!(A && B)  ==  !A || !B
!(A || B)  ==  !A && !B

Первый закон говорит, что отрицание конъюнкции равно дизъюнкции отрицаний. Проверим обе части на конкретных значениях:

System.out.println(!(true && false));     // => true
System.out.println(!true || !false);       // => true

Второй закон говорит, что отрицание дизъюнкции равно конъюнкции отрицаний:

System.out.println(!(true || false));      // => false
System.out.println(!true && !false);        // => false

На практике законы де Моргана помогают упрощать условия. Вместо !(isAdmin || isModerator) можно написать !isAdmin && !isModerator. Второй вариант читается как "не администратор и не модератор", и за ним легче уследить.

Задание

Реализуйте метод notToday(), который проверяет что переданная дата это не сегодняшнее число:

// предположим сегодня 2012-11-25
notToday("2012-11-25"); // false
notToday("2013-11-25"); // true
notToday("2013-09-01"); // true

Для получения текущей даты в виде строки: LocalDate.now().toString().

Полезное

Команда проекта находится в телеграм-сообществе. Там можно задать любой вопрос и повлиять на проект

Нашли ошибку? Есть что добавить? Пулреквесты приветствуются