1. Introduction
In Java's if-else statements we can take a certain action when an expression is true, and an alternative when it is false. In this tutorial, we'll learn about 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"); }
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 might be incomplete code, and seems a long-winded way of handling only the negative condition. We might instead 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 were 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.
For example:
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 you want to not the outcome of an expression, you 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.
For example:
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.
For example:
!(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 discussed the not operator and how it can be used with boolean values, expressions and in if-else statements.
We also looked at 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.