5.1 Boolean Expressions
Key terms: conditional execution, decision statement, expression, operand, binary operator, unary operator, ternary operator, Boolean expression, Boolean literal, relational operator, shallow equality, deep equality
So far we have seen only sequential execution of code: each statement of a method is executed in turn. This chapter deals with conditional execution, which enables one or more statements to be executed only if a specified condition holds. Java has several decision statements for this purpose. Before introducing them, it is necessary to understand how expressions are constructed and evaluated in Java.
5.1.1 Expressions and Operators
An expression is a collection of values combined by operators to produce a single value. The
values are called operands. An operand can be an explicit value, a value returned by a method,
or another expression. Most operators in Java are binary operators; that is, they are applied to
exactly two operands. The addition operator (+), for example, combines two numeric values to form
a sum. Java also has several unary operators, which act on a single operand, and even a
ternary operator (three operands) introduced later in this chapter.
Boolean expressions are expressions that evaluate to true or false. There are two Boolean
literals in Java, true and false. Recall that boolean is one of the primitive types. A
boolean variable can be assigned one of these literals, or the value of another Boolean
expression.
Java's relational operators can be used to construct Boolean expressions involving numbers. For
example, x < 0 is true if the value of x is less than zero. Java’s other relational operators
are <= (less than or equal to), >, >=, == (equals), and != (not equals).
5.1.2 Deep Equality
It is usually a mistake to compare object references with the == operator. Listing 5.1.2
highlights the underlying problem.
Listing 5.1.2 - DeepEquality.java
package chap05.sect1;
import java.math.BigInteger;
/**
* Demonstrates the difference between shallow and deep equality.
*
* @author Drue Coles
*/
public class DeepEquality {
public static void main(String[] args) {
int v1 = 123;
int v2 = 123;
System.out.printf(" int values: %d == %d is %b %n", v1, v2, v1 == v2);
BigInteger b1 = BigInteger.valueOf(123);
BigInteger b2 = BigInteger.valueOf(123);
// test shallow equality
System.out.printf("BigIntegers: %s == %s is %b %n", b1, b2, b1 == b2);
// test deep equality
System.out.printf("BigIntegers: %s.equals(%s) is %b %n", b1, b2, b1.equals(b2));
}
}
Output 5.1.2
int values: 123 == 123 is true
BigIntegers: 123 == 123 is false
BigIntegers: 123.equals(123) is true
The first line of output is no surprise, but what about the second? The key fact here is that b1
and b2 are object references, not objects. They are the memory locations of two different
BigIntegers that happen to be in the same state (both represent the number 123). This is why the
expression b1 == b2 is false.
If x and y are object references, the expression x == y is a test for shallow equality —
whether they refer to the same object. Programmers generally intend to compare the states of
two objects rather than their identities. The condition of two objects being in the same state is
known as deep equality, and BigInteger has an equals method to test for it. The equals
method is used in Listing 5.1.2 to generate the third line of output.