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.