Chapter 7.J

Java Boolean Logic

Boolean Logic in Java

Subsections of Java Boolean Logic

Booleans in Java

The Java programming language supports Boolean values as a primitive data type named boolean. It also includes Boolean keywords true and false to represent each possible value. Notice that these keywords are not capitalized, unlike some other programming languages.

To declare a Boolean variable in Java, we can use the same basic syntax that we used for other variable types:

boolean b;

We can then assign a value of true or false to that variable:

boolean b;
b = true;

We can also combine the two statements into a single statement:

boolean b = false;

Boolean Operators

Java also supports most of the Boolean operators discussed earlier in the chapter. Let’s look at a few examples.

Not !

In Java, the not operator is the exclamation point !, placed before a Boolean value. It will invert the value of the variable, changing true to false and false to true.

Here is a quick example:

boolean b = true;
boolean c = !b;
System.out.println(c); // false

This program will output false, which is the inverted value of b.

And &&

To perform the and operation, Java uses two ampersands && placed between Boolean values. Let’s look at an example:

boolean a = true;
boolean b = true;
boolean c = false;
System.out.println(a && b); // true
System.out.println(b && c); // false

This program will output true on the first line, since we know that both a and b are true. On the second line, it will output false, since c is false, even though b is true.

Or ||

Similarly, Java uses two vertical pipes || to represent the or operator. On most keyboards, we can find that key above the Enter key. Here’s an example of how it can be used in code:

boolean a = true;
boolean b = false;
boolean c = false;
System.out.println(a || b); // true
System.out.println(b || c); // false

Once again, this program will output true on the first line, since a is true, even though b is false. On the second line, it will output false, since both b and c are false.

Short-Circuit Operators

According to the Java documentation, Java also supports using a single & for and, and a single | for or when dealing with Boolean values. Why shouldn’t we just use these operators instead?

It turns out that there is a fundamental difference in how the Java compiler handles these operators. The double-character operators && and || are called logical operators and short-circuit operators. In some scenarios, the system only needs to look at the first value in the statement to determine the result. For example, the statement x || (y || z) will always be true if x is true, without needing to consider the values in y or z. The same works for x && (y && z) when x is false, which will result in the entire statement being false. For larger Boolean expressions, the use of these short-circuit operators can make our programs run much faster and more efficiently.

The single-character operators & and | bit-wise comparison operators and are not short-circuited. So, the system will evaluate each part of the statement before determining the outcome. For boolean values, the bit-wise operators will evaluate to the same answer as the logical operators.

However you should not use them for this purpose. First, because they will slow your programs executions. Second, because it will obscure your intent to future readers of your program. At some distance point in the future, a programmer will see you used a bit-wise operator, assume there must be a reason you did not using the logical one, and lose valuable time trying to figure out why you did not use the logical operator.

You can read more about Bitwise Operations on Wikipedia. We will not use them in this course.

Exclusive Or

Java does not support a logical exclusive or, but we can build a similar statement using other operators.

boolean a = true;
boolean b = false;
boolean c = true;
System.out.println((a || b) && !(a && b)); // true
System.out.println((a || c) && !(a && c)); // false

In this example, the first line will be true, since a is true but b is false. However, the second line will output false, since both a and c are true .

Comparison Operators

We can also use the comparison operators ==, !=, <, <=, >, and >= to compare variables containing numbers, which will result in a Boolean value. Here’s an example showing those operators in action:

int x = 1;
int y = 2;
double z = 3.0;

System.out.println(x < y);  // true
System.out.println(x <= 1); // true
System.out.println(x > 2);  // false
System.out.println(x >= z); // false

System.out.println(x == 1); // true
System.out.println(x != y); // true

As we can see, each of the comparison operators works just as we’d expect, and outputs a Boolean value of either true or false, depending on the result of the comparison.

Chaining Operators is Not Allowed

Like most high level languages, Java does not allow the chaining of comparison operators. 10 <= x <=20, which is a pretty standard math notation for x is between 10 and 20, will not work. First the compiler will evaluate 10 <=x as a boolean, then it will throw a fit about trying to compare a boolean and and int for the <= 20 part.

You will need to write this as 10 <= x && x <= 20.

Order of Operations

Now that we’ve introduced some additional operators, we should also see where they fit in with the other operators in Java. Here is an updated list giving the appropriate operator precedence for Java, with new entries in bold:

  1. Parentheses
  2. Postfix: Increment ++ & Decrement -- after variable*
  3. Prefix: Inverse -, Not !, Increment ++ & Decrement -- before variable*
  4. Multiplicative: Multiplication *, Division /, and Modulo %
  5. Additive: Addition +, Subtraction -
  6. Relational: <, >, <=, >=
  7. Equality: ==, !=
  8. Logical And: &&
  9. Logical Or: ||
  10. Assignment: =, +=, -=, *=, /=, %=

Subgoals Review

Working with Boolean expressions in Java is the same as working with any other type of expression. So, we can use the same subgoals we learned in a previous chapter to help us evaluate and write new Boolean logic expressions. Here’s a quick review of those subgoals.

Analyzing Expressions

To analyze an expression involving variables and mathematical operators in code, here are some mental subgoals we can use:

1. Check Types

First, we must determine whether the data type of the expression is compatible with the data type of the variable we want to store it in. In Java, we must be very careful to make sure we are only storing whole numbers in the integer data type, and floating point values in the double data type.

2. Perform Prefix Operations

Next, we should look at the expression to determine if there are any prefixed operations that must occur first. In Java, for example, we could find a prefixed increment operator like ++x, so we’ll need to update the value of x before moving to the next step.

3. Solve Arithmetic Equation

At this point, we can solve the arithmetic equation using the order of operations for our language. This simply involves the process of substituting values for variables and performing the requested operations. However, once again we must be careful to make sure that the operands provided to each operator are valid and produce the correct data type. The example we saw earlier for handling a large equation showed us a great way to work through this process.

4. Confirm Data Type of Result & Store It

Once we’ve solved the arithmetic equation, we should be left with a variable on the left side of the equals sign and a single value on the right side. So, once again, we should confirm that the value on the right can be stored in the data type of the variable on the left.

5. Perform Postfix Operations

Finally, if the original expression included any postfix operations, such as a postfixed decrement like x-- in Java, we’ll need to update the value of x before moving on to the next line.

Writing Expressions

Here are the subgoals for writing a new expression:

1. Find Variable in Problem Statement

The first step is to determine which part of the problem statement will be represented by a variable. Sometimes this is obvious, and other times it is not. This may be a new variable that we are creating, or it could be an update to an existing variable.

2. Determine Name and Data Type of Variable

Once we’ve found a variable to work with, we must also determine the variable’s name and data type. Once again, this may be obviously found in the problem statement, but other times we must think a bit more about what type of data will be stored in the variable. Of course, we should also make sure the variable has a descriptive and memorable name if we are creating a new one.

3. Build Arithmetic Equation with Operators

Now that we’ve isolated our variable, we must build an arithmetic equation and operators required to produce the desired value. This may involve using additional variables in our equations as well.

4. Build Expression

Once we have our arithmetic equation, we can then build the overall expression. This usually consists of three parts: the variable on the left, an assignment operator in the middle, and the arithmetic equation on the right.

5. Make sure Operators and Operands are Compatible

Finally, once we’ve constructed the overall expression, we should check and make sure that all operators and operands are compatible. This means making sure we are using the correct operators and conversions to produce the desired data type as output.

Example

Let’s look at an example to see how we can use these steps to create an evaluate a Boolean expression to match a problem statement.

Consider the following problem statement:

Create a program to determine if a user has exactly 5 apples, or fewer oranges than bananas. If so, the program should output true, otherwise it should output false. For this program, assume the user has 4 apples, 6 oranges, and 8 bananas.

Let’s go through the subgoal steps above to write this program.

  1. First, we can read the problem statement to see that we should have at least three variables - one for apples, oranges, and bananas. In addition, we may need a fourth variable to store the Boolean result that we’d like to output.

  2. The second subgoal is pretty straightforward. We can easily create three integer variables, apples, oranges, and bananas for each type of fruit, and a Boolean variable result to store the result of our Boolean logic expression.

  3. Next, we’ll need to build our arithmetic equation. For this program, we need to determine if the user has exactly 5 apples, or apples == 5. We also need to know if the user has fewer oranges than bananas, or oranges < bananas. Finally, we can put those together using the or operator as indicated in the problem statement, so the final equation would be (apples == 5) || (oranges < bananas).

  4. Now we can build our program itself. Here’s one possible solution:

int apples = 4;
int oranges = 6;
int bananas = 8;

boolean result = (apples == 5) || (oranges < bananas);

System.out.println(result);
  1. Finally, we can verify that the operators and operands are compatible. Specifically, on either side of the or operator ||, we see that each side is a smaller expression that will result in a Boolean value, so the data type of each operand will be correct.

Using subgoals makes it very easy to work through this process, one step at a time.