2.2.1 Asking Whether Two Values Are Equal
In Topic 2.1 you described algorithms that make decisions: “If the guess matches the secret number, say You win.” Before a program can make that choice, it has to answer the question inside it: does the guess match? Every program you have written so far computes numbers and text. Now you need a way to compute an answer to a yes-or-no question.
Java already has a type for yes-or-no answers. Recall from Topic 1.2 that boolean is a primitive type with exactly two values, true and false. So what is needed is a way to write a question whose answer Java works out as one of those two values.
That is what a comparison does. You write two values with a symbol between them, and Java checks how the two values relate. Think of it like asking a referee a question that can only be answered “yes” or “no”: Java never answers “maybe” or “7”. The answer is always true or false.
A relational operator is a symbol that compares two values and produces a boolean result. The first two relational operators ask about sameness:
| Operator | Read it as | true when |
Example |
|---|---|---|---|
== |
“is equal to” | the two values are the same | a == b |
!= |
“is not equal to” | the two values are not the same | a != b |
Both are two characters typed with no space between them. == is two equals signs; != is an exclamation mark followed by an equals sign. Java uses two equals signs because a single = already has a job: it is the assignment operator from Topic 1.4, which stores a value. == stores nothing; it only asks.
An expression that Java evaluates to true or false is called a Boolean expression. guess == secret is a Boolean expression. So is guess != secret. Every expression built with a relational operator is a Boolean expression, because the operator’s result is always a boolean value. (Boolean is capitalized here because, like the type boolean, it is named after the mathematician George Boole.)
Key idea
A relational operator compares two values and produces a boolean. a == b is true when the values are the same;
a != b is true when they are different. For primitive types, Java compares the actual values.
Worked example: Checking a guess
A guessing game compares the player’s guess with a secret number. Watch the result of each comparison, and notice that the comparisons themselves never change either variable.
int guess = 7;
int secret = 7;
System.out.println(guess == secret);
System.out.println(guess != secret);
guess = 4;
System.out.println(guess == secret);
System.out.println(guess != secret);| Line | What Java does | guess |
secret |
Printed |
|---|---|---|---|---|
| 1 | Stores 7. |
7 | ||
| 2 | Stores 7. |
7 | 7 | |
| 3 | 7 == 7: the values are the same. |
7 | 7 | true |
| 4 | 7 != 7: they are not different. |
7 | 7 | false |
| 5 | Assignment: replaces 7 with 4. |
4 | 7 | |
| 6 | 4 == 7: the values are not the same. |
4 | 7 | false |
| 7 | 4 != 7: they are different. |
4 | 7 | true |
Output:
true
false
false
trueTwo things to notice. First, println prints a boolean result exactly as it prints a boolean literal from Topic 1.3: the word true or false, with no quotation marks. Second, for the same two values, == and != always give opposite answers. If one is true, the other is false.
The values on each side of == are primitive values here, so Java compares those values directly: is the int in guess the same number as the int in secret? Now vary the types. The next example compares an int with a double, compares two boolean values, and stores a result in a boolean variable instead of printing it right away.
Worked example: Mixing types and storing the answer
int boxes = 3;
double weight = 3.0;
boolean sameNumber = boxes == weight;
System.out.println(sameNumber);
boolean doorOpen = true;
System.out.println(doorOpen != false);Line 3 has two operators, = and ==. As in every assignment (Topic 1.4), Java finishes the right side before it stores anything:
| Step | What Java does | Result |
|---|---|---|
| 1 | Look up boxes (3) and weight (3.0). |
|
| 2 | One side is a double, so the int 3 is widened to 3.0, as in Topic 1.5. |
|
| 3 | 3.0 == 3.0 is the same value. |
true |
| 4 | Store true in the boolean variable sameNumber. |
true |
Line 4 prints true. Line 6 compares two boolean values: doorOpen holds true, and true != false asks whether those differ. They do, so it prints true too.
true
trueThe variable on line 3 must be declared boolean, because the value being stored is true or false, not a number.
Watch out
Writing = when you mean ==. The two symbols look alike, and in math class one = means “is equal to.” In Java, one = means “store.” A student who wants to check a guess writes:
int guess = 7;
boolean correct = guess = 7;
System.out.println(correct);This does not compile:
error: incompatible types: int cannot be converted to booleanJava reads line 2 as two assignments: store 7 in guess, and then store the result of that assignment (the int 7) in correct. A boolean variable cannot hold the number 7, so Java refuses. The fix is to ask instead of store: boolean correct = guess == 7;. (Exact error wording can vary between Java versions.)
Pause and try
Question 1 · Tracing
What does this code print? Track lives as you go.
int lives = 3;
int maxLives = 5;
System.out.println(lives == maxLives);
System.out.println(lives != maxLives);
lives = 5;
System.out.println(lives == maxLives);
boolean roomForMore = lives != maxLives;
System.out.println(roomForMore);Check your reasoning
false
true
true
false| Line | Comparison or action | Result |
|---|---|---|
| 3 | 3 == 5 |
false |
| 4 | 3 != 5 |
true |
| 5 | lives becomes 5 |
|
| 6 | 5 == 5 |
true |
| 7 | 5 != 5, stored in roomForMore |
false |
| 8 | prints roomForMore |
false |
Line 7 does not print anything; it stores false in roomForMore, and line 8 prints what was stored. If you got true on the last line, you may have used the old value 3; line 5 replaced it before line 7 ran.
Reread 2.2.1 Asking Whether Two Values Are Equal if your output differed.
Question 2 · Debugging
This code should print whether the entered PIN matches the saved PIN. It does not compile. Find the error, explain what Java sees, and correct the line.
int pin = 1234;
int entered = 1243;
boolean match = entered = pin;
System.out.println(match);Check your reasoning
The error is on line 3. entered = pin uses the assignment operator, so Java reads it as “store pin in entered.” The result of that assignment is the int 1234, and a boolean variable cannot hold an int, so Java reports incompatible types: int cannot be converted to boolean. The programmer wanted to ask a question, not store a value.
Corrected code:
int pin = 1234;
int entered = 1243;
boolean match = entered == pin;
System.out.println(match);It prints false, because 1243 == 1234 compares two different numbers. (Notice that even if the original had compiled, it would have overwritten the entered PIN, which is never what a PIN check should do.)
Reread the Watch Out in 2.2.1 Asking Whether Two Values Are Equal if you missed it.
2.2.2 Comparing Sizes: Less Than and Greater Than
Many decisions do not ask “the same or not?” They ask “how big?” A test is passed with a score of at least 70. A ride lets you on if you are taller than a line on the sign. A coupon works if the total is under a limit. == and != cannot answer these, because a score of 85 is not equal to 70 and yet it passes.
For questions about which number is larger, Java has four more relational operators. You know the ideas from math; only the symbols for “or equal” are typed differently, because a keyboard has no ≤ or ≥ key, so Java spells them with two characters:
| Operator | Read it as | true when |
|---|---|---|
< |
“is less than” | the left value is smaller |
> |
“is greater than” | the left value is larger |
<= |
“is less than or equal to” | the left is smaller or the same |
>= |
“is greater than or equal to” | the left is larger or the same |
For <= and >=, the angle bracket comes first and the equals sign second, written together with no space: say “less than or equal,” in that order, and type it in that order. These four operators work on numbers (int and double), because only numbers have a “larger” and “smaller.” Like == and !=, each one produces a boolean.
Key idea
<, >, <=, and >= compare two numbers and produce true or false. The “or equal” versions are also true
when the two values are the same.
Worked example: Exactly on the passing line
A class passes students with a score of at least 70. The most important value to test is the boundary itself, a score of exactly 70, because that is where the four operators disagree.
int score = 70;
System.out.println(score > 70);
System.out.println(score >= 70);
System.out.println(score < 70);
System.out.println(score <= 70);| Line | Question Java answers | Result |
|---|---|---|
| 2 | Is 70 greater than 70? |
false |
| 3 | Is 70 greater than or equal to 70? |
true |
| 4 | Is 70 less than 70? |
false |
| 5 | Is 70 less than or equal to 70? |
true |
false
true
false
trueA number is never greater than or less than itself, so > and < are false here. The “or equal” operators let the boundary value count, so >= and <= are true. Because “at least 70” includes 70 itself, score >= 70 is the right test; score > 70 would fail a student who scored exactly 70.
Everyday words map onto the operators, and the boundary decides which one you need:
| Words | Includes the boundary? | Operator |
|---|---|---|
| more than, over, above | No | > |
| at least, no fewer than | Yes | >= |
| less than, under, below | No | < |
| at most, no more than | Yes | <= |
Now vary the values: a double compared with an int, and negative numbers.
Worked example: A price and two cold mornings
double price = 19.99;
int budget = 20;
System.out.println(price < budget);
int lowToday = -5;
int lowYesterday = -12;
System.out.println(lowToday > lowYesterday);
System.out.println(lowToday <= lowYesterday);| Line | Comparison | Reasoning | Result |
|---|---|---|---|
| 3 | 19.99 < 20 |
The int 20 is widened to 20.0; 19.99 is smaller. |
true |
| 6 | -5 > -12 |
On a number line, -5 is to the right of -12, so it is greater. | true |
| 7 | -5 <= -12 |
-5 is neither smaller than nor equal to -12. | false |
true
true
falseLine 6 is the one to study. It is tempting to think 12 is “bigger” than 5, so -12 must be bigger than -5. But the operators compare positions on the number line, not the size of the digits. A low of -5 degrees is warmer, and greater, than a low of -12.
Watch out
Typing the symbols in the wrong order. Because people say “equal or greater” as often as “greater or equal,” students sometimes type => or =<:
int score = 70;
System.out.println(score => 70);error: illegal start of expressionJava does not have a => comparison operator, so it cannot make sense of the line. The same happens with a space in the middle, as in > =. Write the angle bracket first and the equals sign right after it: score >= 70. (Exact error wording can vary between Java versions.)
Pause and try
Question 3 · Multiple choice
A roller coaster lets riders on if they are at least 48 inches tall. The int variable height holds a rider’s height in inches. Which Boolean expression is true exactly when the rider may ride?
height > 48height >= 48height => 4848 >= height
Check your reasoning
B. “At least 48” includes 48 itself, so the test must be true for 48 and for every taller height. height >= 48 does exactly that.
- A is wrong:
>leaves out the boundary. A rider who is exactly 48 inches tall getsfalseand is turned away. - C is wrong:
=>is not a Java operator, so the expression does not compile. - D is wrong: it reverses the question.
48 >= heightistruewhen the rider is 48 inches or shorter.
Reread 2.2.2 Comparing Sizes: Less Than and Greater Than if you chose differently.
Question 4 · Tracing
What does this code print?
double speed = 54.5;
int limit = 55;
System.out.println(speed < limit);
System.out.println(speed >= limit);
int depth = -30;
System.out.println(depth > -20);
System.out.println(limit <= 55);Check your reasoning
true
false
false
true- Line 3:
54.5 < 55(theint55 is widened to55.0). 54.5 is smaller, sotrue. - Line 4:
54.5 >= 55isfalse; it is the opposite question from line 3. - Line 6:
-30 > -20isfalse. On the number line, -30 is to the left of -20, so it is smaller, even though 30 is more than 20. - Line 7:
55 <= 55istrue, because the “or equal” part lets the boundary count.
Reread 2.2.2 Comparing Sizes: Less Than and Greater Than if your output differed.
2.2.3 Arithmetic Happens Before Comparison
Real questions usually involve a calculation. “Can 14 apples be shared equally among 4 students?” is really “is the remainder of 14 divided by 4 equal to 0?” “Will two shirts at $20.75 cost more than $40?” is “is 20.75 times 2 greater than 40?” So a comparison often has arithmetic on one or both sides.
Recall from Topic 1.3 that Java works out an expression in a fixed order: *, /, and % before + and -. Relational operators come after all of the arithmetic operators. In apples % students == 0, Java first computes apples % students, and only then compares the result with 0. This order makes sense: a comparison needs two finished numbers, so Java finishes each side first. You can add parentheses for readability, as in (apples % students) == 0, but they do not change the answer.
Key idea
In an expression that mixes arithmetic and comparison, Java does all the arithmetic first, then compares the two
results. The whole expression still produces a single boolean.
Worked example: Sharing apples and buying shirts
int apples = 14;
int students = 4;
System.out.println(apples % students == 0);
System.out.println(apples / students >= 3);
double total = 12.5 + 8.25;
System.out.println(total * 2 > 40);Each comparison is worked out in two steps: arithmetic, then the comparison.
| Line | Arithmetic first | Then compare | Result |
|---|---|---|---|
| 3 | 14 % 4 is 2 |
2 == 0 |
false |
| 4 | 14 / 4 is 3 (integer division) |
3 >= 3 |
true |
| 5 | 12.5 + 8.25 is 20.75, stored in total |
||
| 6 | 20.75 * 2 is 41.5 |
41.5 > 40 |
true |
false
true
trueLine 3 says the apples cannot be shared equally: 4 students get 3 apples each and 2 are left over. Line 4 uses integer division from Topic 1.3, so 14 / 4 is 3, not 3.5, before the comparison happens.
The remainder operator is especially useful in comparisons. A whole number is even exactly when dividing it by 2 leaves no remainder, so number % 2 == 0 is a Boolean expression that is true for even numbers and false for odd ones. Here it is with different values, plus a comparison that adds two variables first:
int tickets = 18;
int chairs = 25;
System.out.println(tickets % 2 == 0);
System.out.println(chairs % 2 == 0);
System.out.println(chairs % 2 != 0);
System.out.println(tickets + chairs > 40);true
false
true
true
18 % 2 is 0, so line 3 is true. 25 % 2 is 1, so line 4 (1 == 0) is false and line 5 (1 != 0) is true: the same remainder, opposite questions. Line 6 adds first, 18 + 25 is 43, then checks 43 > 40.
Watch out
Comparing double results with ==. Topic 1.5 showed that 0.1 + 0.2 is stored as 0.30000000000000004. That tiny round-off error matters for ==, which compares the actual stored values:
double sum = 0.1 + 0.2;
System.out.println(sum);
System.out.println(sum == 0.3);0.30000000000000004
falseOn paper the sum is exactly 0.3, so students expect true. But Java compares the value it actually stored, and that value is not exactly 0.3. Two common fixes: ask whether the two double values are very close, using Math.abs from Topic 1.11 to measure the distance between them, or keep amounts that must be exact (such as money in cents) in int variables, which have no round-off error.
double sum = 0.1 + 0.2;
System.out.println(Math.abs(sum - 0.3) < 0.000001);
int cents = 10 + 20;
System.out.println(cents == 30);true
trueLine 2 asks “is the gap between sum and 0.3 smaller than one millionth?” It is, so the answer is true. Line 4 compares two int values, which are always exact.
Watch out
Writing a range the way math does. In math, 60 < t < 80 means “t is between 60 and 80.” Java does not read it that way:
int temperature = 72;
System.out.println(60 < temperature < 80);error: bad operand types for binary operator '<'
first type: boolean
second type: intJava works left to right. 60 < temperature becomes true, and then Java is asked to work out true < 80. A boolean is not a number, so it cannot be less than 80, and the message says exactly that: the first value is a boolean, the second an int. A comparison produces a boolean, and a boolean cannot be compared by size. Checking two conditions at once needs a new kind of operator that joins Boolean expressions; that is Topic 2.5. For now, write each comparison on its own: 60 < temperature and temperature < 80. (Exact wording can vary between Java versions.)
Pause and try
Question 5 · Tracing
A movie runs for 135 minutes. What does this code print? Show the arithmetic step for each line.
int minutes = 135;
System.out.println(minutes / 60 == 2);
System.out.println(minutes % 60 > 15);
System.out.println(minutes % 2 != 0);
System.out.println(minutes - 35 <= 100);Check your reasoning
true
false
true
true| Line | Arithmetic first | Then compare | Result |
|---|---|---|---|
| 2 | 135 / 60 is 2 |
2 == 2 |
true |
| 3 | 135 % 60 is 15 |
15 > 15 |
false |
| 4 | 135 % 2 is 1 |
1 != 0 |
true |
| 5 | 135 - 35 is 100 |
100 <= 100 |
true |
Line 2 uses integer division (two whole hours fit in 135 minutes). Line 3 is the trap: the remainder is exactly 15, and 15 is not greater than itself. Line 4 says 135 is odd.
Reread 2.2.3 Arithmetic Happens Before Comparison if your output differed.
Question 6 · Multiple choice
What does System.out.println(0.1 * 3 == 0.3); print?
truefalse0.3- Nothing; you cannot use
==withdoublevalues.
Check your reasoning
B. The multiplication happens first. 0.1 cannot be stored exactly in a double, so 0.1 * 3 comes out very slightly different from 0.3 (it prints as 0.30000000000000004). == compares the stored values, which differ, so the result is false.
- A is wrong: it is the answer on paper, but Java compares the values it actually stored, and round-off error makes them differ.
- C is wrong: a Boolean expression produces
trueorfalse, never a number. The multiplication is only a step along the way. - D is wrong:
==works ondoublevalues and compiles fine. It is just risky because of round-off error.
Reread the round-off Watch Out in 2.2.3 Arithmetic Happens Before Comparison if you chose differently.
2.2.4 Storing and Printing Boolean Results
A program often needs the answer to a question more than once, or wants to give it a meaningful name. “Is this person a teenager?” might be needed in several places, and isTeen says more than age >= 13 does each time it appears. Topic 1.4 showed that a variable can hold the result of any expression of its type. A Boolean expression has type boolean, so its result goes in a boolean variable, and a good name for that variable reads like a yes-or-no question or statement: isTeen, passed, canAfford.
There is one thing to understand clearly. When Java runs boolean isTeen = age >= 13;, it evaluates the comparison once, at that moment, and stores the answer, true or false. The variable holds the answer, not the question. If age changes later, isTeen does not change by itself. It changes only if you assign to it again.
Key idea
A Boolean expression has type boolean, so its result can be stored in a boolean variable. The variable stores the
answer at the moment of assignment; it does not update when the values that produced it change.
Worked example: The answer, not the question
int age = 12;
boolean isTeen = age >= 13;
System.out.println(isTeen);
age = 14;
System.out.println(isTeen);
isTeen = age >= 13;
System.out.println(isTeen);| Line | What Java does | age |
isTeen |
Printed |
|---|---|---|---|---|
| 1 | Stores 12. |
12 | ||
| 2 | 12 >= 13 is false; stores false. |
12 | false | |
| 3 | Prints isTeen. |
12 | false | false |
| 4 | Replaces 12 with 14. isTeen is untouched. |
14 | false | |
| 5 | Prints isTeen. |
14 | false | false |
| 6 | 14 >= 13 is true; stores true. |
14 | true | |
| 7 | Prints isTeen. |
14 | true | true |
Line 5 surprises many students: the person is now 14, yet isTeen still prints false. Nothing re-asked the question until line 6.
Because a Boolean expression has type boolean, it cannot be stored in a variable of another type. Java checks this before the program runs:
int answer = 5 > 3;
System.out.println(answer);error: incompatible types: boolean cannot be converted to int
5 > 3 is true, a boolean, and an int variable holds only whole numbers. There is no automatic conversion between boolean and the number types in Java. (Exact wording can vary between Java versions.)
Printing a result with a label uses string concatenation from Topic 1.15: + with a String on one side turns a boolean into the text true or false. But concatenation brings an order-of-operations trap.
Watch out
Forgetting parentheses around a comparison in a label. A student wants to print Even: true:
int count = 6;
System.out.println("Even: " + count % 2 == 0);error: bad operand types for binary operator '=='
first type: String
second type: intHere is the order Java follows. % comes first: count % 2 is 0. Then +, which comes before ==: "Even: " + 0 is the String "Even: 0". Last, == is asked to compare "Even: 0" with the int 0. A String and an int cannot be compared, so the code does not compile; the error message names exactly those two types. Students expect the comparison to “go with” the label because that is how they read it, but Java follows operator order, not intent.
The fix is parentheses, which make Java finish the comparison before joining it to the label:
int count = 6;
System.out.println("Even: " + (count % 2 == 0));
System.out.println("Remainder: " + count % 2);Even: true
Remainder: 0Line 3 needs no extra parentheses, because % already happens before +. Only a relational operator needs them, since relational operators come after +.
Pause and try
Question 7 · Tracing
A club needs more than half of its 50 members to vote yes. What does this code print?
int votes = 26;
int members = 50;
boolean majority = votes * 2 > members;
System.out.println("Majority: " + majority);
System.out.println("Tie: " + (votes * 2 == members));
votes = 25;
System.out.println("Majority: " + majority);
System.out.println("Tie: " + (votes * 2 == members));Check your reasoning
Majority: true
Tie: false
Majority: true
Tie: true| Line | What happens | Printed |
|---|---|---|
| 3 | 26 * 2 is 52; 52 > 50 is true; stored in majority. |
|
| 4 | Prints the stored value. | Majority: true |
| 5 | 52 == 50 is false (worked out now, inside parentheses). |
Tie: false |
| 6 | votes becomes 25. majority is not re-evaluated. |
|
| 7 | Prints the stored value, still true. |
Majority: true |
| 8 | 25 * 2 is 50; 50 == 50 is true, worked out now. |
Tie: true |
Line 7 still says true because majority holds the answer from line 3. Line 8 differs from line 5 because its comparison is written right there in the println, so it is evaluated again with the new value of votes.
Reread 2.2.4 Storing and Printing Boolean Results if your output differed.
Question 8 · Debugging
This code should print whether a score of 82 passes. It does not compile. Find the error, explain it, and correct the line.
int score = 82;
String passed = score >= 70;
System.out.println(passed);Check your reasoning
The error is on line 2. score >= 70 is a Boolean expression, so its value is the boolean true, not text. A String variable cannot hold a boolean, and Java reports incompatible types: boolean cannot be converted to String. The quotation-free word true is a boolean value, not the String "true".
Corrected code:
int score = 82;
boolean passed = score >= 70;
System.out.println(passed);It prints true, because 82 >= 70.
Reread 2.2.4 Storing and Printing Boolean Results if you missed it.
2.2.5 Comparing Strings and Other Objects
Every comparison so far used primitive values. Programs also need to compare text: does the typed password match the saved one? Does this name come before that one alphabetically? It is natural to reach for == and <. Neither does what you want with a String.
Recall from Topics 1.12 and 1.13 that a variable of a reference type, such as String, does not hold the object itself. It holds a reference to the object, which you can think of as the object’s address in memory. And each use of new creates a brand-new object at a new address.
== always compares what is stored in the two variables. For an int, that is the number. For a String variable, that is the reference. So for reference types, first == second asks “do these two variables refer to the very same object?” It does not look inside the objects at all. Two different objects can hold exactly the same characters, the way two copies of the same book are still two books.
To ask whether two strings hold the same text, use equals from Topic 1.15.
Key idea
With reference types, == and != compare references: whether two variables refer to the same object. To compare the
text inside two strings, use equals.
Worked example: Two objects, same text
String first = new String("Tiger42");
String second = new String("Tiger42");
System.out.println(first.equals(second));
System.out.println(first == second);
System.out.println(first != second);Lines 1 and 2 each use new, so there are two separate String objects. Memory looks like this (the arrows stand for references):
first ──► [ "Tiger42" ] object 1
second ──► [ "Tiger42" ] object 2| Line | Question | Result |
|---|---|---|
| 3 | Same characters? (equals looks inside) |
true |
| 4 | Same object? (== compares references) |
false |
| 5 | Different objects? | true |
true
false
trueLine 4 is the surprise. The text matches, but the arrows point to two different objects, so == says false. If a login program used == to check a password, a correct password could be rejected. Never rely on == to compare the text of two strings; its answer depends on how the strings were created, not on what they say. Topic 2.6 explores comparing references in more detail.
The size operators <, >, <=, and >= do not work on strings at all. To ask which string comes first alphabetically, use compareTo from Topic 1.15, which returns an int, and then compare that int with 0 using a relational operator. That turns compareTo into a yes-or-no question.
Worked example: Which word comes first?
String a = "apple";
String b = "banana";
System.out.println(a.compareTo(b) < 0);
System.out.println(a.compareTo(b) == 0);
System.out.println(b.compareTo(a) > 0);
System.out.println(a.length() < b.length());| Line | int from the method |
Then compare | Result |
|---|---|---|---|
| 3 | "apple".compareTo("banana"): negative |
< 0 |
true |
| 4 | the same negative number | == 0 |
false |
| 5 | "banana".compareTo("apple"): positive |
> 0 |
true |
| 6 | lengths 5 and 6 |
5 < 6 |
true |
true
false
true
trueRead line 3 as “apple compared to banana is less than zero,” which means “apple comes before banana.” You never need the exact number compareTo returns, only whether it is negative, zero, or positive. Line 6 is different: length() returns an int, so < compares two ordinary numbers.
Watch out
Using < directly on strings. A student who wants to know whether "apple" comes before "banana" writes:
String a = "apple";
String b = "banana";
System.out.println(a < b);error: bad operand types for binary operator '<'
first type: String
second type: String< works only on numbers, and a String is not a number, so the code does not compile. The fix is a.compareTo(b) < 0. (Exact wording can vary between Java versions.)
Pause and try
Question 9 · Multiple choice
What does this code print?
String saved = new String("ok");
String typed = new String("ok");
System.out.println(saved == typed);
System.out.println(saved.equals(typed));truethentruefalsethentruetruethenfalsefalsethenfalse
Check your reasoning
B. Each new creates its own String object, so saved and typed refer to two different objects. == compares the references, which differ, so line 3 prints false. equals compares the characters, which are the same, so line 4 prints true.
- A is wrong: it treats
==as if it compared text. For reference types it compares references. - C is wrong: it swaps the two methods’ jobs.
equalsis the one that looks at the characters. - D is wrong: the two strings do hold exactly the same characters, so
equalsistrue.
Reread 2.2.5 Comparing Strings and Other Objects if you chose differently.
Question 10 · Tracing
What does this code print?
String first = "Lopez";
String second = "Lee";
System.out.println(first.compareTo(second) < 0);
System.out.println(second.compareTo(first) < 0);
System.out.println(first.equals("lopez"));
System.out.println(first.length() > second.length());Check your reasoning
false
true
false
true- Line 3:
"Lopez"and"Lee"match atL, then differ atoversuse.ocomes aftere, so"Lopez".compareTo("Lee")is positive, andpositive < 0isfalse. - Line 4: the same pair in the other order gives a negative number, so
< 0istrue: Lee comes before Lopez. - Line 5:
equalsis case-sensitive (Topic 1.15).Landldiffer, sofalse. - Line 6:
5 > 3compares twointlengths, sotrue.
If you said line 3 is true because “Lopez” is longer, remember that compareTo uses dictionary order, not length.
Reread 2.2.5 Comparing Strings and Other Objects if your output differed.
Putting it together
A theater’s ticket kiosk answers several yes-or-no questions about a customer before selling a ticket. This program uses every idea in the chapter. Try predicting all six lines before reading the trace.
Worked example: A ticket kiosk
public class TicketCheck
{
public static void main(String[] args)
{
int age = 15;
double cash = 12.0;
double ticketPrice = 11.5;
int seatsLeft = 40;
int groupSize = 6;
String rating = new String("PG-13");
boolean oldEnough = age >= 13;
boolean canAfford = cash >= ticketPrice;
System.out.println("Old enough: " + oldEnough);
System.out.println("Can afford: " + canAfford);
System.out.println("Exact cash: " + (cash == ticketPrice));
System.out.println("Room for group: " + (seatsLeft - groupSize >= 0));
System.out.println("Even group: " + (groupSize % 2 == 0));
System.out.println("Rated PG-13: " + rating.equals("PG-13"));
}
}Lines 5–10 set up the values: a 15-year-old with $12.00, a ticket price of $11.50, 40 seats left, a group of 6, and a rating string made with new.
| Line | Expression | Work | Result |
|---|---|---|---|
| 11 | age >= 13 |
15 >= 13; stored in oldEnough |
true |
| 12 | cash >= ticketPrice |
12.0 >= 11.5; stored in canAfford |
true |
| 15 | cash == ticketPrice |
12.0 == 11.5 |
false |
| 16 | seatsLeft - groupSize >= 0 |
arithmetic first: 40 - 6 is 34; 34 >= 0 |
true |
| 17 | groupSize % 2 == 0 |
6 % 2 is 0; 0 == 0 |
true |
| 18 | rating.equals("PG-13") |
same characters | true |
Old enough: true
Can afford: true
Exact cash: false
Room for group: true
Even group: true
Rated PG-13: trueLook at the details. Lines 13 and 14 print stored boolean variables, so no parentheses are needed. Lines 15–17 put a comparison inside a label, so each comparison is wrapped in parentheses; without them, + would join the label first and the code would not compile. Line 18 needs no extra parentheses because equals is a method call, which Java finishes before it does any +. And line 18 uses equals, not ==: rating was made with new, so rating == "PG-13" would compare two different objects.
Vocabulary
| Term | Definition | Example |
|---|---|---|
| relational operator | A symbol that compares two values and produces a boolean: ==, !=, <, >, <=, >= |
score >= 70 |
| Boolean expression | An expression that Java evaluates to true or false |
count % 2 == 0 |
| even | A whole number that leaves no remainder when divided by 2 | 18 % 2 == 0 |
Chapter summary
- A relational operator compares two values and produces a
boolean, so any expression built with one is a Boolean expression whose value istrueorfalse. ==asks whether two values are the same and!=whether they differ. For primitive types these compare the actual values, which is whydoubleround-off error can make==givefalse.<,>,<=, and>=compare numbers. Only the “or equal” versions aretruewhen the two values are the same, so the boundary decides which operator a question needs.- Arithmetic happens before comparison, and
+happens before comparison too, so a comparison inside a printed label needs parentheses. - A Boolean result can be stored in a
booleanvariable; it holds the answer at that moment and does not update on its own. - For reference types,
==and!=compare references, not contents. Compare string text withequals, and alphabetical order withcompareToand0.
Review questions
Question 11 · Multiple choice
The variable points holds 50. Which expression evaluates to false?
points >= 50points % 10 == 0points / 3 > 16points != 49
Check your reasoning
C. Arithmetic first: 50 / 3 is integer division, so it is 16, not 16.67. Then 16 > 16 is false, because a number is not greater than itself.
- A is wrong:
50 >= 50istrue; the “or equal” part includes the boundary. - B is wrong:
50 % 10is0, and0 == 0istrue. - D is wrong: 50 is different from 49, so
!=givestrue.
Reread 2.2.2 Comparing Sizes: Less Than and Greater Than and 2.2.3 Arithmetic Happens Before Comparison if you chose differently.
Question 12 · Tracing
A gym reads a member’s age, account balance, and membership level, then checks a $10.00 entry fee. Write the exact output.
import java.util.Scanner;
public class GymEntry
{
public static void main(String[] args)
{
Scanner input = new Scanner("17 9.5 Gold");
int age = input.nextInt();
double balance = input.nextDouble();
String level = input.next();
double fee = 10.0;
boolean adult = age >= 18;
System.out.println("Adult: " + adult);
System.out.println("Short: " + (fee - balance));
System.out.println("Enough money: " + (balance >= fee));
System.out.println("Gold member: " + level.equals("Gold"));
System.out.println("Odd age: " + (age % 2 == 1));
}
}Check your reasoning
Adult: false
Short: 0.5
Enough money: false
Gold member: true
Odd age: trueThe Scanner reads 17 into age, 9.5 into balance, and "Gold" into level (Topic 1.4).
| Line | Expression | Work | Printed |
|---|---|---|---|
| 12 | age >= 18 |
17 >= 18; stored |
|
| 13 | adult |
stored value | Adult: false |
| 14 | fee - balance |
10.0 - 9.5 (arithmetic only) |
Short: 0.5 |
| 15 | balance >= fee |
9.5 >= 10.0 |
Enough money: false |
| 16 | level.equals("Gold") |
same characters | Gold member: true |
| 17 | age % 2 == 1 |
17 % 2 is 1; 1 == 1 |
Odd age: true |
Line 14 is not a Boolean expression at all; it prints a double. It shows the parentheses doing the same job as in the comparison lines: finishing a calculation before + joins it to the label.
Reread 2.2.4 Storing and Printing Boolean Results and 2.2.5 Comparing Strings and Other Objects if your output differed.
Question 13 · Debugging
Two players type their team colors. This program should print Same team: true for the input blue blue, but it prints Same team: false. Find the error, explain why it prints false, and correct the line.
import java.util.Scanner;
public class TeamWrong
{
public static void main(String[] args)
{
Scanner input = new Scanner("blue blue");
String myTeam = input.next();
String yourTeam = input.next();
System.out.println("Same team: " + (myTeam == yourTeam));
}
}Check your reasoning
The error is on line 10. myTeam == yourTeam compares references, not text. Each call to next() creates a new String object for the word it reads, so myTeam and yourTeam refer to two different objects that happen to hold the same characters. == asks “same object?”, and the answer is no. The code compiles, so only the wrong output reveals the bug.
Corrected code:
import java.util.Scanner;
public class TeamFixed
{
public static void main(String[] args)
{
Scanner input = new Scanner("blue blue");
String myTeam = input.next();
String yourTeam = input.next();
System.out.println("Same team: " + myTeam.equals(yourTeam));
}
}equals compares the characters, so it prints Same team: true. No extra parentheses are needed around the method call.
Reread 2.2.5 Comparing Strings and Other Objects if you missed it.
Question 14 · Short answer
Two students want to test whether the int variable total is a multiple of 5. One writes total % 5 == 0; the other writes total / 5 == 0. Give the value of each expression when total is 15 and when total is 3, and explain which test is correct.
Check your reasoning
Model answer: When total is 15: 15 % 5 is 0, so total % 5 == 0 is true; 15 / 5 is 3, so total / 5 == 0 is false. When total is 3: 3 % 5 is 3, so the first test is false; 3 / 5 is 0 with integer division, so the second test is true. The % test is correct: a number is a multiple of 5 exactly when dividing by 5 leaves no remainder. The / test asks a different question, whether the whole-number quotient is zero, so it gives the wrong answer for both values.
A complete answer must:
- give all four results:
trueandfalsefor 15,falseandtruefor 3, - say that arithmetic is done before the comparison, including integer division for
3 / 5, and - explain that “multiple of 5” means “remainder 0,” which is what
%measures.
Reread 2.2.3 Arithmetic Happens Before Comparison if your answer differed.
Question 15 · Multiple choice
What does this code print?
String x = "Zoo";
String y = "apple";
System.out.println(x.compareTo(y) < 0);
System.out.println(x.equals("zoo"));
System.out.println(x.length() == y.length());
System.out.println(y.compareTo(x) < 0);false,false,false,truetrue,false,false,falsefalse,true,false,truetrue,true,true,false
Check your reasoning
B. Line 3: Topic 1.15 showed that compareTo puts every uppercase letter before every lowercase letter. Z is uppercase and a is lowercase, so "Zoo" comes first, "Zoo".compareTo("apple") is negative, and < 0 is true. Line 4: equals is case-sensitive, so "Zoo" and "zoo" differ: false. Line 5: lengths 3 == 5 is false. Line 6: the reversed call is positive, so < 0 is false.
- A is wrong: it uses everyday alphabetical order, where z comes last.
compareToranks uppercase before lowercase. - C is wrong: it also ignores case, both in
compareToand inequals. - D is wrong: it treats
equalsas ignoring case and compares the lengths incorrectly; 3 is not equal to 5.
Reread 2.2.5 Comparing Strings and Other Objects if you chose differently.
Reflection
Check each statement. If the answer is “not yet,” reread the linked subsection.
- I can predict the result of == and != and explain why = cannot be used to compare. Reread
- I can choose between <, >, <=, and >= for a question, paying attention to the boundary value. Reread
- I can work out a comparison that contains arithmetic, and explain why == on double results is risky. Reread
- I can store a Boolean result in a boolean variable and print it with a label, using parentheses where needed. Reread
- I can explain what == does with two String objects and use equals and compareTo instead. Reread