Main Page

Previous Next

Logical Operators

The tests we have put in the if expressions have been relatively simple so far, except perhaps for the last one. Real life is typically more complicated. You will often want to combine a number of conditions so that you execute a particular course, for example, if they are all true simultaneously. You can ride the roller coaster if you are over 12 years old, over four feet tall, and less than six feet six. Failure on any count and it's no go. Sometimes, though, you may need to test for any one of a number of conditions being true, for example, you get a lower price entry ticket if you are under 16, or over 65.

You can deal with both of these cases, and more, using logical operators to combine several expressions that have a value true or false. Because they operate on boolean values they are also referred to as boolean operators. There are five logical operators that operate on boolean values:

Symbol

Long name

&

logical AND

&&

conditional AND

|

logical OR

||

conditional OR

!

logical negation (NOT)

These are very simple, the only point of potential confusion being the fact that we have the choice of two operators for each of AND and OR. The extra operators are the bitwise & and | from the previous chapter that you can also apply to boolean values where they have an effect that is subtly different from && and ||. We'll first consider what each of these are used for in general terms, then we'll look at how we can use them in an example.

Boolean AND Operations

You can use either AND operator, && or &, where you have two logical expressions that must both be true for the result to be true – that is, you want to be rich and healthy. Either operator will produce the same result from the logical expression. We will come back to how they are different in a moment. First, let's explore how they are used. All of the following discussion applies equally well to & as well as &&.

Let's see how logical operators can simplify the last example. You could use the && operator if you were testing a variable of type char to determine whether it contained an uppercase letter or not. The value being tested must be both greater than or equal to 'A' AND less than or equal to 'Z'. Both conditions must be true for the value to be a capital letter. Taking the example from our previous program, with a value stored in a char variable symbol, we could implement the test for an uppercase letter in a single if by using the && operator:

if(symbol >= 'A' && symbol <= 'Z')
   System.out.println("You have the capital letter " + symbol);

If you take a look at the precedence table back in Chapter 2, you will see that the relational operators will be executed before the && operator, so no parentheses are necessary. Here, the output statement will be executed only if both of the conditions combined by the operator && are true. However, as we have said before, it is a good idea to add parentheses if they make the code easier to read. It also helps to avoid mistakes.

In fact, the result of an && operation is very simple. It is true only if both operands are true, otherwise the result is false.

We can now rewrite the set of ifs from the last example.

Try It Out – Deciphering Characters the Easy Way

Replace the outer if-else loop and its contents in LetterCheck.java with the following:

if(symbol >= 'A' && symbol <= 'Z') {       // Is it a capital letter
  System.out.println("You have the capital letter " + symbol);

} else {
  if(symbol >= 'a' && symbol <= 'z') {    // or is it a small letter?
    System.out.println("You have the small letter " + symbol);

  } else {                                  // It is not less than z
    System.out.println("The code is not a letter");
  }
}

How It Works

Using the && operator has condensed the example down quite a bit. We now can do the job with two ifs, and it's certainly easier to follow what's happening.

You might want to note that when the statement in an else clause is another if, the if is sometimes written on the same line as the else, as in:

if(symbol >= 'A' && symbol <= 'Z') {          // Is it a capital letter
  System.out.println("You have the capital letter " + symbol);

} else if(symbol >= 'a' && symbol <= 'z') {   // or is it a small letter?
  System.out.println("You have the small letter " + symbol);

} else {                                      // It is not less than z
  System.out.println("The code is not a letter");
}

I think the original is clearer, so I prefer not to do this.

&& versus &

So what distinguishes && from & ? The difference between them is that the conditional && will not bother to evaluate the right-hand operand if the left-hand operand is false, since the result is already determined in this case to be false. This can make the code a bit faster when the left-hand operand is false.

For example, consider the following statements:

int number = 50;
if(number<40 && (3*number - 27)>100) {
  System.out.println("number = " + number);
}

Here the expression (3*number - 27)>100 will never be executed since the expression number<40 is always false. On the other hand, if you write the statements as:

int number = 50;
if(number<40 & (3*number - 27)>100) {
  System.out.println("number = " + number);
}

the effect is different. The whole logical expression is always evaluated, so even though the left-hand operand of the & operator is false and the result is a forgone conclusion once that is known, the right hand operand ((3*number - 27)>100) will still be evaluated. So, we can just use && all the time to make our programs a bit faster and forget about &, right? Wrong – it all depends on what you are doing. Most of the time you can use &&, but there are occasions when you will want to be sure that the right-hand operand is evaluated – and equally, there are instances where you want to be certain the right-hand operand won't be evaluated if the left operand is false.

The first situation can arise for instance when the right hand expression involves modifying a variable – and you want the variable to be modified in any event. An example of a statement like this is:

if(++value%2 == 0 & ++count < limit) {
  // Do something
}

Here, the variable count will be incremented in any event. If you use && instead of &, count will only be incremented if the left operand of the AND operator is true. You get a different result depending on which operator is used.

We can illustrate the second situation with the following statement:

if(count > 0 && total/count > 5) {
  // Do something...
}

In this case the right operand for the && operation will only be executed if the left operand is True – that is, when count is positive. Clearly, if we were to use & here, and count happened to be zero, we will be attempting to divide the value of total by 0, which in the absence of code to prevent it, will terminate the program.

Boolean OR Operations

The OR operators, | and ||, apply when you want a true result if either or both of the operands are true. The conditional OR, ||, has a similar effect to the conditional AND, in that it omits the evaluation of the right-hand operand when the left-hand operand is true. Obviously if the left operand is true, the result will be True regardless of whether the right operand is true or false.

Let's take an example. A reduced entry ticket price is issued to under 16 year olds and to those aged 65 or over; this could be tested using the following if:

if(age < 16 || age>= 65) {
  ticketPrice *= 0.9;         // Reduce ticket price by 10%
}

The effect here is to reduce ticketPrice by ten percent if either condition is true. Clearly in this case both conditions cannot be true.

With an | or an || operation, you only get a false result if both operands are false. If either or both operands are true, the result is true.

Boolean NOT Operations

The third type of logical operator, !, takes one boolean operand and inverts its value. So if the value of a boolean variable, state, is true, then the expression !state has the value false, and if it is false then !state becomes true. To see how the operator is used with an expression, we could rewrite the code fragment we used to provide discounted ticket price as:

if(!(age >= 16 && age < 65)) {
  ticketPrice *= 0.9;         // Reduce ticket price by 10%
}

The expression (age >= 16 && age < 65) is true if age is from 16 to 64. People of this age do not qualify for the discount, so the discount should only be applied when this expression is false. Applying the ! operator to the result of the expression does what we want.

We could also apply the ! operator in an expression that was a favorite of Charles Dickens:

!(Income>Expenditure)

If this expression is true, the result is misery, at least as soon as the bank starts bouncing your checks.

Of course, you can use any of the logical operators in combination if necessary. If the theme park decides to give a discount on the price of entry to anyone who is under 12 years old and under 48 inches tall, or someone who is over 65 and over 72 inches tall, you could apply the discount with the test:

if((age < 12 && height < 48) || (age > 65 && height > 72)) {
   ticketPrice *= 0.8;             // 20% discount on the ticket price
}

The parentheses are not strictly necessary here, as && has a higher precedence than ||, but adding the parentheses makes it clearer how the comparisons combine and makes it a little more readable.

Important 

Don't confuse the bitwise operators &, |, and !, with the logical operators that look the same. Which type of operator you are using in any particular instance is determined by the type of operand with which you use it. The bitwise operators apply to integer types and produce an integer result. The logical operators apply to operands that have boolean values and produce a result of type booleantrue or false. You can use both bitwise and logical operators in an expression if it is convenient to do so.

Character Testing Using Standard Library Methods

While testing characters using logical operators is a useful way of demonstrating how these operators work, in practice there is an easier way. The standard Java packages provide a range of standard methods to do the sort of testing for particular sets of characters such as letters or digits that we have been doing with if statements. They are all available within the class Character, which is automatically available in your programs. For example, we could have written the if statement in our LetterCheck program as shown in the following example.

Try It Out – Deciphering Characters Trivially

Replace the code body of the LetterCheck class with the following code:

if(Character.isUpperCase(symbol)) {
  System.out.println("You have the capital letter " + symbol);

} else {
  if(Character.isLowerCase(symbol)) {
    System.out.println("You have the small letter " + symbol);

  } else {
    System.out.println("The code is not a letter");
  }
}

How It Works

The isUpperCase() method returns true if the char value passed to it is uppercase, and false if it is not. Similarly, the isLowerCase() method returns true if the char value passed to it is lowercase.

The following table shows some of the other methods included in the class Character that you may find useful for testing characters. In each case the argument to be tested is of type char, and is placed between the parentheses following the method name:

Method

Description

isDigit()

Returns the value true if the argument is a digit (0 to 9) and false otherwise.

isLetter()

Returns the value true if the argument is a letter, and false otherwise.

isLetterOrDigit()

Returns the value true if the argument is a letter or a digit, and false otherwise.

isWhitespace()

Returns the value true if the argument is whitespace, which is any one of the characters:

   space (' '),
tab ('\t'),
newline ('\n'),
carriage return ('\r'),
form feed ('\f')

The method returns false otherwise.

You will find information on other methods in the class Character in the documentation for the class that is part of the Java Development Kit.

Previous Next
JavaScript Editor Java Tutorials Free JavaScript Editor