Unit 2 · 20 min

2.6 Comparing Boolean Expressions

Equivalent expressions always agree, and == on objects asks about identity, not contents.

Summary, objectives and course and exam description (CED) codes

Two Boolean expressions are equivalent if they evaluate to the same value in all cases, and a truth table can prove it. De Morgan's laws create equivalent expressions: !(a && b) is equivalent to !a || !b, and !(a || b) is equivalent to !a && !b. For objects, == and != compare object references (including checks against null), while a class's equals method compares objects using their attributes.

By the end of this session you can

  • 2.6.A Compare equivalent Boolean expressions.
  • 2.6.B Develop code to compare object references using Boolean expressions and determine the result of these expressions.

2.6.A2.6.A.12.6.A.22.6.B2.6.B.12.6.B.22.6.B.3

Reviewed against the CED on

Know this already? Jump to the checkpoint.

1LearnThe notes, the traps and how to remember them

1. Equivalent expressions and truth tables

Two Boolean expressions are equivalent if they evaluate to the same value in all cases. A truth table can prove they are equivalent 2.6.A.1: list every combination of true and false for the variables, evaluate both expressions in each row, and compare. With two variables there are 4 rows; with three variables there are 8.

Are !(a && b) and !a || !b equivalent?

a b a && b !(a && b) !a !b !a || !b
true true true false false false false
true false false true false true true
false true false true true false true
false false false true true true true

The columns for !(a && b) and !a || !b match in every row, so the expressions are equivalent.

Are !(a && b) and !a && !b equivalent? Row 2 (a true, b false) gives true for the first and false for the second. One row that differs is enough to show two expressions are not equivalent.

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

Output:

true
true
false

2. De Morgan’s laws

De Morgan’s laws can be applied to Boolean expressions to create equivalent Boolean expressions 2.6.A.2:

  • !(a && b) is equivalent to !a || !b
  • !(a || b) is equivalent to !a && !b

To apply a law: move the ! onto each part, and switch && to || (or || to &&). When the parts are comparisons, negate each comparison:

Comparison Its negation
x > 5 x <= 5
x < 5 x >= 5
x >= 5 x < 5
x == 5 x != 5

Example: !(temp > 30 || isRaining) becomes temp <= 30 && !isRaining. In words: “not (hot or raining)” means “not hot and not raining”.

int temp = 24;
boolean isRaining = false;
boolean original = !(temp > 30 || isRaining);
boolean rewritten = temp <= 30 && !isRaining;
System.out.println(original + " " + rewritten);

Output:

true true

Watch out: a common wrong answer keeps the > and writes temp < 30. For temp equal to 30, !(temp > 30) is true but temp < 30 is false.

3. Two variables, one object

Two different variables can hold references to the same object. Object references can be compared using == and != 2.6.B.1. The comparison is true only when both references point to the same object; it does not look at what is inside the objects.

String teamA = new String("Lions");
String teamB = new String("Lions");
String favorite = teamA;
System.out.println(teamA == favorite);
System.out.println(teamA == teamB);
System.out.println(teamA != teamB);

Output:

true
false
true
Variable Refers to
teamA object 1 (“Lions”)
favorite object 1 (same object as teamA)
teamB object 2 (“Lions”, a separate object)

Variables like teamA and favorite, which refer to the same object, are called aliases.

Watch out: two string literals with the same characters, such as "Lions" and "Lions", may share one object, so == can happen to be true. Never rely on this: compare string contents with equals.

4. Comparing a reference with null

A reference variable can hold null, which means it does not refer to any object. Comparing a reference with null, using == or !=, tells you whether it actually refers to an object 2.6.B.2.

String winner = null;
if (winner == null) {
    System.out.println("No winner yet");
}
winner = "Tigers";
if (winner != null) {
    System.out.println("Winner: " + winner + " (" + winner.length() + " letters)");
}

Output:

No winner yet
Winner: Tigers (6 letters)

Calling a method such as length() on a null reference throws a NullPointerException. Check for null first, and put that check on the left of && so short-circuit evaluation protects the call: winner != null && winner.length() > 2.

5. equals: equivalency by attributes

Classes often define their own equals method to specify what makes two objects of that class equivalent. The decision is most often based on attributes of the two objects 2.6.B.3.

The String class is the example you use most. Its equals method treats two strings as equivalent when they have the same sequence of characters, even if they are separate objects.

String typed = new String("open sesame");
String password = "open sesame";
System.out.println(typed == password);
System.out.println(typed.equals(password));
System.out.println(typed.equals("Open sesame"));

Output:

false
true
false

Uppercase and lowercase letters are different characters, so the last comparison is false.

Other classes choose their own criteria. A class for library cards might call two cards equal when their card numbers match; a class for points on a grid might compare both coordinates. When an exam question gives you a class with an equals method, read its description to see which attributes it compares. (Writing your own replacement for the equals method is outside the AP® course and exam.)

Question you are asking Use
Do these two variables refer to the same object? ==
Does this variable refer to any object? == null or != null
Are these two objects equivalent (same attribute values)? equals

Lock it in: memory hooks

  • De Morgan's lawsBreak the line, change the sign: push the ! inside, flip && and ||.
  • Negating comparisons> becomes <=, < becomes >=, == becomes !=. The equals part always switches sides.
  • == versus equals== asks "same object?"; equals asks "same contents?"

Common misconceptions

  • "!(a && b) is the same as !a && !b."

    Not quite. De Morgan's law flips the operator: !(a && b) is equivalent to !a || !b. Check with a = true, b = false: !(true && false) is true, but !a && !b is false.

  • "The opposite of x > 5 is x < 5."

    Not quite. The opposite of x > 5 is x <= 5. The value 5 itself makes x > 5 false, so it must make the negation true.

  • "If two variables hold equal-looking objects, == is true."

    Not quite. == asks whether two references refer to the same object. Two separate objects with the same attribute values are not ==, but they can be equal according to the class's equals method.

Exam traps

  • Negating a comparison: !(score >= 60) is score < 60, not score <= 60.
  • !(a && b) is not !a && !b. The operator must flip.
  • One test case is not a proof of equivalence. Check every row of the truth table.
  • Calling a method on a null reference throws a NullPointerException. Check != null first, on the left of &&.

2PracticeRecall it, then check yourself

In 30 seconds

  1. Equivalent Boolean expressions give the same value in every case. A truth table that checks every combination proves it.
  2. De Morgan: !(a && b) equals !a || !b, and !(a || b) equals !a && !b.
  3. Two variables can hold references to the same object (aliases). == and != compare references.
  4. Compare a reference with null (== null or != null) to check whether it refers to an object.
  5. A class's equals method defines equivalency, usually by comparing attributes, such as the characters of two strings.

Cover this list, say the points out loud, then take the checkpoint without scrolling back up.

Checkpoint · 6 questions

Checkpoint: Comparing Boolean Expressions

Pick an answer to mark it. Every answer is explained, and you can try any question again. Your saved score counts first tries only, and stays in this browser.

  1. 1 The int variables x and y have been declared and initialized. Which of the following expressions is equivalent to !(x >= 10 && y != 4)? 2.6.A.2
    Show answer

    Answer: B. By De Morgan's law, !(a && b) is equivalent to !a || !b. The negation of x >= 10 is x < 10, and the negation of y != 4 is y == 4, joined with ||. Keeping && forgets to switch the operator, and x <= 10 is wrong when x is exactly 10.

  2. 2 The boolean variables a and b have been declared and initialized. Which of the following expressions is equivalent to !(a || !b)? 2.6.A.1, 2.6.A.2
    Show answer

    Answer: C. By De Morgan's law, !(p || q) is !p && !q. Here the second part is !b, and !(!b) is b, so the result is !a && b. !a || b forgets to switch || to &&, and !a && !b forgets that negating !b gives b.

  3. 3 Consider the following code segment. What is printed as a result of executing the code segment? 2.6.B.1, 2.6.B.3
    String a = new String("map");
    String b = a;
    String c = new String("map");
    b = c;
    System.out.println((a == b) + " " + (b == c) + " " + a.equals(c));
    Show answer

    Answer: A. After b = c;, b refers to the same object as c, not a. So a == b is false, b == c is true, and a.equals(c) is true because the two strings have the same characters. "true false true" uses the first assignment b = a and ignores the reassignment.

  4. 4 Consider the following code segment. What is printed as a result of executing the code segment? 2.6.B.2, 2.6.A.1
    String nick = null;
    if (nick == null || nick.length() == 0) {
        System.out.println("none");
    } else {
        System.out.println(nick);
    }
    Show answer

    Answer: A. Comparing nick with null is true, so || short-circuits and nick.length() is never called; "none" is printed. A NullPointerException would only happen if length() were called on the null reference. The code compiles, since comparing a reference with null is allowed.

  5. 5 A class Ticket has an equals method that returns true when two tickets have the same seat number. Two different Ticket objects are created, both for seat 14, and are referenced by t1 and t2. Which of the following is true? 2.6.B.1, 2.6.B.3
    Show answer

    Answer: C. == compares object references, and t1 and t2 refer to two different objects, so it is false. The class's equals method decides equivalency by an attribute (the seat number), and both seats are 14, so it is true. Thinking == is true confuses identical attributes with the same object.

  6. 6 A student wants to prove with a truth table that two Boolean expressions using the boolean variables a, b and c are equivalent. How many rows (combinations of values) must the truth table check? 2.6.A.1
    Show answer

    Answer: B. Each variable can be true or false, so there are 2 times 2 times 2 = 8 combinations, and equivalence means the same value in all cases. 3 counts only the variables, and 6 or 9 do not match the doubling for each extra variable.

3PrevailLock it in for exam day

By the numbers

Name each list from memory, then reveal it to check. Each list shows how many items to recall.

  • De Morgan's laws two laws CED 2.6.A.2
    1. !(a && b) is equivalent to !a || !b
    2. !(a || b) is equivalent to !a && !b
  • Ways to compare objects three ways CED 2.6.B.1, 2.6.B.2, 2.6.B.3
    1. == or != between two referencessame object or not
    2. == or != with nulldoes the reference refer to an object
    3. equalsare the objects equivalent, usually by their attributes

Key terms: flip the cards

Read the term, say the definition out loud, then flip to check. Struggling a little to remember is what makes it stick.

  • Equivalent Boolean expressionstap to flip

    Two Boolean expressions that evaluate to the same value in all cases. A truth table can prove they are equivalent.

    Example and CED codes
  • Truth tabletap to flip

    A table that lists every combination of true and false for the variables in Boolean expressions, with the value of each expression in every row.

    Example and CED codes
  • De Morgan's lawstap to flip

    Rules that create equivalent Boolean expressions: !(a && b) is equivalent to !a || !b, and !(a || b) is equivalent to !a && !b.

    Example and CED codes
  • Logical operatorstap to flip

    The operators ! (not), && (and) and || (or), which combine Boolean expressions into a compound Boolean expression. Precedence: !, then &&, then ||.

    Example and CED codes
  • Reference equality (== versus equals)tap to flip

    Using == or != on object references checks whether they refer to the same object. A class's equals method checks whether two objects are equivalent.

    Example and CED codes
  • Object referencetap to flip

    The value a reference variable holds: it can be thought of as the memory address of the object.

    Example and CED codes
  • nulltap to flip

    A special literal meaning a reference variable is not associated with any object.

    Example and CED codes
  • Objecttap to flip

    A specific instance of a class with defined attributes.

    Example and CED codes

Questions students ask

What are De Morgan's laws in Java?

!(a && b) is equivalent to !a || !b, and !(a || b) is equivalent to !a && !b. To apply them, negate each part and switch && with ||.

How do you prove two Boolean expressions are equivalent?

Build a truth table with every combination of true and false for the variables. If both expressions give the same value in every row, they are equivalent.

What is the difference between == and equals for objects?

== compares object references, so it is true only when both refer to the same object. equals compares the objects by the criteria the class defines, usually their attributes.

How do I check if an object reference is null?

Compare it with null using == or !=, for example if (name != null). Never call a method on a reference before checking it is not null.

Was this page helpful?

No names are ever shown, and every public comment is checked by us first. Please do not include personal details. To get a reply, email [email protected].

↑ Top

Enlarged view of the selected figure