1. Introduction
In Java’s if-else statements, we can take a certain action when an expression is true, and an alternate one when it’s false. In this tutorial, we’ll learn how to reverse the logic using the not operator.
2. The if-else Statement
Let’s start with a simple if-else statement:
boolean isValid = true;
if (isValid) {
System.out.println("Valid");
} else {
System.out.println("Invalid");
}
Now what if our program only needs to handle the negative case? How would we re-write the above example?
One option is to simply remove the code in the if block:
boolean isValid = true;
if (isValid) {
} else {
System.out.println("Invalid");
}
However, an empty if block looks like it could be incomplete code, and seems like a long-winded way of handling only the negative condition. Instead, we can try testing if our logical expression evaluates to false:
boolean isValid = true;
if (isValid == false) {
System.out.println("Invalid");
}
The above version is relatively easy to read, though it might be harder to do if the logical expression was more complex. Java has an alternative for us, though, in the form of the not operator:
boolean isValid = true;
if (!isValid) {
System.out.println("Invalid");
}
3. The not Operator
The not operator is a logical operator, represented in Java by the ! symbol. It’s a unary operator that takes a boolean value as its operand. The not operator works by inverting (or negating) the value of its operand.
3.1. Applying the not Operator to a Boolean Value
When applied to a boolean value, the not operator turns true to false and false to true:
System.out.println(!true); // prints false
System.out.println(!false); // prints true
System.out.println(!!false); // prints false
3.2. Applying the not Operator to a Boolean Expression
Since not is a unary operator, when we want to not the outcome of an expression, we need to surround that expression in parenthesis to get the right answer. The expression in the parenthesis is evaluated first, and then the not operator inverts its outcome:
int count = 2;
System.out.println(!(count > 2)); // prints true
System.out.println(!(count <= 2)); // prints false
boolean x = true;
boolean y = false;
System.out.println(!(x && y)); // prints true
System.out.println(!(x || y)); // prints false
We should note that when negating an expression, De Morgan’s laws come into play. In other words, each term in the expression is negated and the operator is reversed.
This can help us to simplify harder to read expressions:
!(x && y) is same as !x || !y
!(x || y) is same as !x && !y
!(a < 3 && b == 10) is same as a >= 3 || b != 10
4. Some Common Pitfalls
Using the not operator can sometimes compromise the readability of our code. Negatives can be harder to understand than positives. Let’s look at some examples.
4.1. Double Negatives
Because the not operator is a negation operator, using it with variables or functions that have a negative name can result in hard to read code. This is similar to natural languages, where double negatives are often considered hard to understand.
For example:
if (product.isActive()) {...}
reads better than
if (!product.isNotActive()) {...}
While our API may not provide an isActive method, we can create one to aid readability.
4.2. Complex Conditions
The not operator can sometimes make an already complex expression even more difficult to read and understand. When this happens, we can simplify the code by reversing the condition or by extracting methods. Let’s look at some examples of conditions made complex by the not operator, and how we can simplify them by reversing the condition:
if (!true) // Complex
if (false) // Simplified
if (!myDate.onOrAfter(anotherDate)) // Complex
if (myDate.before(anotherDate)) // Simplified
if (!(a >= b)) // Complex
if (a < b) // Simplified
if (!(count >= 10 || total >= 1000)) // Complex
if (count < 10 && total < 1000) // Simplified
5. Conclusion
In this article, we explored the not operator and how it can be used with boolean values, expressions, and in if-else statements.
We also discussed some common pitfalls caused by writing expressions in their inverse and how to fix them.
As always the source code for the examples used in this article is available over on GitHub.