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) {
} else {

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 {

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) {

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) {

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.