3 Boolean Expressions and If Statements

3 Boolean Expressions and If Statements

3.1. Boolean ExpressionsBoolean variables or expressions can only have true or false values.3.1...

花野猫

花野猫

更新于 2024-01-23

26217

3.1. Boolean Expressions

Boolean variables or expressions can only have true or false values.

3.1.1. Testing Equality (==)

The operators == and != (not equal) can be used to compare values. They return true or false boolean values.

One = sign changes the value of a variable. Two == equal signs are used to test if a variable holds a certain value, without changing its value!

The following code shows how == is used with primitive types like int.

What will the code below print out? Try to guess before you run it! Note that 1 equal sign (=) is used for assigning a value and 2 equal signs (==) for testing values.

java
public class BoolTest1
{
public static void main(String[] args)
{
int age = 15;
int year = 14;
// Will this print true or false?
System.out.println(age == year);
year = 15;
// Will this print true or false?
System.out.println(age == year);
// Will this print true or false?
System.out.println(age != year);
}
}

3.1.2. Relational Operators (<, >)

The Relational Operators below in Java are used to compare numeric values or arithmetic expressions. Although some programming languages allow using relational operators like < to compare strings, Java only uses these operators for numbers, and uses the methods compareTo and equals for comparing String values.

  • < Less Than

  • > Greater Than

  • <= Less than or equal to

  • >= Greater than or equal to

  • == Equals

  • != Does not equal

If you have trouble telling < and > apart, think of < and > as arrows where the pointy end should point to the smaller value. If < (less than) points towards a smaller number on the left, then it evaluates to true. On the other hand a > (greater than) expression will be true only if the smaller number is on the right hand side. Or maybe you prefer the “hungry alligator” mnemonic beloved by elementary school teachers—think of < and > as the mouths of hungry alligators which always want to eat the bigger number; a < or > expression is only true if the alligator is in fact about to eat the bigger number.

To remember the correct order of the two characters in <= and >=, just write them in the same order you would say them in English: “less than or equal to” not “equal to or less than”.

Coding Exercise

Try to guess what the code below will print out before you run it.

java
public class BoolTest2
{
public static void main(String[] args)
{
int age = 15;
int year = 14;
// Will these print true or false?
System.out.println(age < year);
System.out.println(age > year);
System.out.println(age <= year + 1);
System.out.println(age - 1 >= year);
}
}

3.1.3. Testing with remainder (%)

Here are some boolean expressions that are very useful in coding and remainder is used in many of them:

java
// Test if a number is positive
(number > 0)
//Test if a number is negative
(number < 0)
//Test if a number is even by seeing if the remainder is 0 when divided by 2
(number % 2 == 0)
//Test if a number is odd by seeing if there is a remainder when divided by 2
(number % 2 > 0)
//Test if a number is a multiple of x (or divisible by x with no remainder)
(number % x == 0)

Try the expressions containing the % operator below to see how they can be used to check for even or odd numbers. All even numbers are divisible (with no remainder) by 2.

java
public class BoolMod
{
public static void main(String[] args)
{
int age1 = 15;
int age2 = 16;
int divisor = 2;
System.out.println(
"Remainder of "
+ age1
+ "/"
+ divisor
+ " is "
+ (age1 % divisor));
System.out.println(
"Remainder of "
+ age2
+ "/"
+ divisor
+ " is "
+ (age2 % divisor));
System.out.println("Is " + age1 + " even? " + (age1 % 2 == 0));
System.out.println("Is " + age2 + " even? " + (age2 % 2 == 0));
}
}

The remainder operator has been used quite a bit on the AP CSA exam, so you should be familiar with it.

  • Use it to check for odd or even numbers. If num % 2 != 0 is true, num is odd and if num % 2 == 0 is true then num is even.

  • You can also use remainder to check if any number is evenly divisible by any other: If num1 % num2 == 0 is true then num1 is evenly divisible by num2.

  • Use it to get the last digit from an integer number: num % 10 gives us the rightmost digit of num.

  • Use it to get the number of minutes left when you convert a total number of minutes to hours and minutes:

java
int totalMinutes = 345;
int hours = totalMinutes / 60; // Number of whole hours, i.e. 5
int minutes = totalMinutes % 60; // Number of minutes left over, i.e. 45
  • Use it whenever you have limit in the value, and you need to wrap around to zero if the value goes over the limit: the value of num % limit will always be in the range from 0 (inclusive) to limit (exclusive) as long as num and limit are both positive.

A warning: because Java’s % is a remainder operator and not a true mathematical modulo operator (as we discussed briefly in section 1.4) you can’t check if a number is odd with the expression num % 2 == 1.

That expression will be true if num is positive and odd and false when num is even, both of which are correct. But if num is negative and odd, its remainder when divided by 2 is -1, not 1 and this expression will evaluate to false. Thus you should always use num % 2 != 0 to check if num is odd.

3.1.4. Summary

  • Primitive values and reference values can be compared using relational operators (i.e., == and !=) in Java.

  • Arithmetic expression values can be compared using relational operators (i.e., <, >, <=, >=) in Java.

  • An expression involving relational operators evaluates to a boolean value of true or false.

3.1.5. AP Practice

Consider the following statement.

java
boolean x = (5 % 3 == 0) == (3 > 5);

What is the value of x after the statement has been executed?

A. false
B. true
C. (5 % 3 == 0)
D. (3 > 5)
E. 2


Consider the following Boolean expression in which the int variables x and y have been properly declared and initialized.

java
(x >= 10) == (y < 12)

Which of the following values for x and y will result in the expression evaluating to true ?

A. x = 10 and y = 12
B. x = 9 and y = 9
C. x = 10 and y = 11
D. x = 10 and y = 13
E. x = 9 and y = 12

3.2. if Statements and Control Flow

The statements in a Java main method normally run or execute one at a time in the order they are found from top to bottom. If statements (also called conditionals or selection) change the flow of control through the program so that some code is only run when something is true. In an if statement, if the condition is true then the next statement or a block of statements will execute. If the condition is false then the next statement or block of statements is skipped.

The order that statements execute in a conditional
The order that statements execute in a conditional

A conditional uses the keyword if followed by Boolean expression inside of an open parenthesis ( and a close parenthesis ) and then followed by a single statement or block of statements. The single statement or block of statements are only executed if the condition is true. The open curly brace { and a close curly brace } are used to group a block of statements together. It is recommended to always put in the curly braces even if you have just one statement under the if statement. The questions you will see on the AP exam will use curly braces.

java
// A single if statement
if (boolean expression)
Do statement;
// Or a single if with {}
if (boolean expression)
{
Do statement;
}
// A block if statement: { } required
if (boolean expression)
{
Do Statement1;
Do Statement2;
...
Do StatementN;
}

Imagine that your cell phone wanted to remind you to take an umbrella if it was currently raining in your area when it detected that you were leaving the house.The variable isRaining is a boolean variable that is either true or false. If it is true then the message Take an umbrella! will be printed and then execution will continue with the next statement which will print Drive carefully. Run the code below to see this. Try changing the code above to boolean isRaining = false;. What will it print?

java
public class Test1
{
public static void main(String[] args)
{
boolean isRaining = true;
if (isRaining)
{
System.out.println("Take an umbrella!");
}
System.out.println("Drive carefully");
}
}

3.2.1. Relational Operators in If Statements

Most if statements have a boolean condition that uses relational operators like ==, !=, <, >, <=, >=, as we saw in the last lesson.

Coding Exercise

Run the following active code a couple times until you see all the possible outputs. It prints out whether a random number is positive or equal to 0. Add another if statement that tests if it is a negative number.

java
public class TestNumbers
{
public static void main(String[] args)
{
// Get a random number from -10 up to 10.
int number = (int) (Math.random() * 21) - 10;
System.out.println("The number is " + number);
// is it positive?
if (number > 0)
{
System.out.println(number + " is positive!");
}
// is it 0?
if (number == 0)
{
System.out.println(number + " is zero!");
}
// is it negative?
// Add another if statement
}
}

Consider the following code segment. What is printed as a result of executing the code segment?

java
int x = 3;
if (x > 2)
{
x = x * 2;
}
if (x > 4)
{
x = 0;
}
System.out.print(x);

3.2.2. Common Errors with If Statements

Here are some rules to follow with if statements to avoid some common errors:

  • Always use curly braces ({ and }) to enclose the block of statements under the if condition. Java doesn’t care if you indent the code—it goes by the { }.

  • Don’t put in a semicolon ; after the first line of the if statement, if (test);. The if statement is a multiline block of code that starts with the if condition and then { the body of the if statement }.

  • Always use ==, not =, in the condition of an if statement to test a variable. One = assigns, two == tests!

The code below doesn’t work as expected. Fix it to only print Wear a coat and Wear gloves when isCold is true.

java
public class Test1
{
public static void main(String[] args)
{
boolean isCold = false;
if (isCold = true);
System.out.println("Wear a coat");
System.out.println("Wear gloves");
}
}

3.2.3. Summary

  • if statements test a boolean expression and if it is true, go on to execute the following statement or block of statements surrounded by curly braces ({}) like below.
java
// A single if statement
if (boolean expression)
Do statement;
// A block if statement
if (boolean expression)
{
Do Statement1;
Do Statement2;
...
Do StatementN;
}
  • Relational operators (==, !=, <, >, <=, >=) are used in boolean expressions to compare values and arithmetic expressions.

  • Conditional (if) statements affect the flow of control by executing different statements based on the value of a Boolean expression.

3.2.4. AP Practice

Consider the following code segment.

java
int speed = 35;
boolean rain = false;
if (rain)
{
speed -= 10;
}
if (rain == false)
{
speed += 5;
}
if (speed > 35)
{
speed = speed - 2;
}
System.out.println(speed);

What is printed as a result of executing the code segment?

A. 28
B. 35
C. 38
D. 25
E. 33


Consider the following code segment.

java
int x = 5;
if (x < 5)
{
x = 3 * x;
}
if (x % 2 == 1)
{
x = x / 2;
}
System.out.print(2*x + 1);

What is printed as a result of executing the code segment?

A. 3
B. 11
C. 31
D. 15
E. 5

3.3. Two-way Selection: if-else Statements

What if you want to pick between two possibilities? In programming, you can use the if keyword followed by a statement or block of statements and then the else keyword also followed by a statement or block of statements.

java
// A block if/else statement
if (boolean expression)
{
statement1;
statement2;
}
else
{
do other statement;
and another one;
}
// A single if/else statement
if (boolean expression)
Do statement;
else
Do other statement;

The following flowchart demonstrates that if the condition (the boolean expression) is true, one block of statements is executed, but if the condition is false, a different block of statements inside the else clause is executed.

The order that statements execute in a conditional with 2 options: if and else
The order that statements execute in a conditional with 2 options: if and else

The else will only execute if the condition is false.

java
public class Test2
{
public static void main(String[] args)
{
boolean isHeads = true;
if (isHeads)
{
System.out.println("Let's go to the game");
}
else
{
System.out.println("Let's watch a movie");
}
System.out.println("after conditional");
}
}

3.3.1. Nested Ifs and Dangling Else

If statements can be nested inside other if statements. Sometimes with nested ifs we find a dangling else that could potentially belong to either if statement. The rule is that the else clause will always be a part of the closest unmatched if statement in the same block of code, regardless of indentation.

java
// Nested if with dangling else
if (boolean expression)
if (boolean expression)
Do statement;
else // belongs to closest if
Do other statement;
java
public class DanglingElseTest
{
public static void main(String[] args)
{
boolean sunny = true;
boolean hot = false;
if (sunny)
if (hot)
System.out.println("Head for the beach!");
else // Which if is else attached to??
System.out.println("Bring your umbrella!");
}
}

3.3.2. Summary

  • If statements can be followed by an associated else part to form a 2-way branch:
java
if (boolean expression)
{
Do statement;
}
else
{
Do other statement;
}
  • A two way selection (if/else) is written when there are two sets of statements: one to be executed when the Boolean condition is true, and another set for when the Boolean condition is false.

  • The body of the “if” statement is executed when the Boolean condition is true, and the body of the “else” is executed when the Boolean condition is false.

  • Use 2 test-cases to find errors or validate results to try both branches of an if/else statement.

  • The else statement attaches to the closest unmatched if statement in the same block of statements.

3.3.3. AP Practice

Consider the following code segment where a range of “High”, “Middle”, or “Low” is being determined where x is an int and a “High” is 80 and above, a “Middle” is between 50 - 79, and “Low” is below 50.

java
if (x >= 80)
{
System.out.println("High");
}
if (x >= 50)
{
System.out.println("Middle");
}
else
{
System.out.println("Low");
}

Which of the following initializations for x will demonstrate that the code segment will not work as intended?

A. 80
B. 60
C. 50
D. 30
E. -10

3.4. Multi-Selection: else-if Statements

Using if/else statements, you can even pick between 3 or more possibilites. Just add else if for each possibility after the first if, and else before the last possibility.

java
// 3 way choice with else if
if (boolean expression)
{
statement1;
}
else if (boolean expression)
{
statement2;
}
else
{
statement3;
}
java
public class TestElseIf
{
public static void main(String[] args)
{
int x = 2;
if (x < 0)
{
System.out.println("x is negative");
}
else if (x == 0)
{
System.out.println("x is 0");
}
else
{
System.out.println("x is positive");
}
System.out.println("after conditional");
}
}

Here is a flowchart for a conditional with 3 options like in the code above.

The order that statements execute in a conditional with 3 options: if, else if, and else
The order that statements execute in a conditional with 3 options: if, else if, and else

What does the following code print when x has been set to -5? What does the following code print when x has been set to 2000?

java
if (x < 0)
{
System.out.println("x is negative");
}
else if (x == 0)
{
System.out.println("x is zero");
}
else
{
System.out.println("x is positive");
}

The else-if connection is necessary if you want to hook up conditionals together. In the following code, there are 4 separate if statements instead of the if-else-if pattern. Will this code print out the correct grade? First, trace through the code to see why it prints out the incorrect grade. Use the Code Lens button. Then, fix the code by adding in 3 else’s to connect the if statements and see if it works.

java
public class IfDebug
{
public static void main(String[] args)
{
int score = 93;
String grade = "";
if (score >= 90)
{
grade = "A";
}
if (score >= 80)
{
grade = "B";
}
if (score >= 70)
{
grade = "C";
}
if (score >= 60)
{
grade = "D";
}
else
{
grade = "F";
}
System.out.println(grade);
}
}

Finish the following code so that it prints “Plug in your phone!” if the battery is below 50, “Unplug your phone!” if it is above 100, and “All okay!” otherwise. Change the battery value to test all 3 conditions.

java
public class BatteryTest
{
public static void main(String[] args)
{
int battery = 60;
System.out.println("All okay!");
}
}

3.4.1. Summary

  • A multi-way selection is written when there are a series of conditions with different statements each for condition.

  • Multi-way selection is performed using if-else-if statements such that exactly one section of code is executed based on the first condition that evaluates to true.

java
// 3 way choice with else if
if (boolean expression)
{
statement1;
}
else if (boolean expression)
{
statement2;
}
else
{
statement3;
}

3.4.2 AP Practice

Assume an int variable x has been properly declared and initialized. Which of the following code segments will print out “High” if x is 66 and above, “Medium” is x is between 33-65, and “Low” if x is below 33.

java
I. if (x > 66)
{
System.out.println("High");
}
else if (x > 33)
{
System.out.println("Medium");
}
else {
System.out.println("Low");
}
II. if (x < 33)
{
System.out.println("Low");
}
else if (x < 66)
{
System.out.println("Medium");
}
else {
System.out.println("High");
}
III. if (x >= 66)
{
System.out.println("High");
}
if (x >= 33)
{
System.out.println("Medium");
}
if (x < 33)
{
System.out.println("Low");
}

A. I only
B. II only
C. III only
D. I and II only
E. II and III only

3.5. Compound Boolean Expressions

3.5.1. And (&&), Or (||), and Not (!)

What if you want two things to be true before the body of the conditional is executed? Use && as a logical and to join two Boolean expressions and the body of the condition will only be executed only if both are true.

What if you want to go out and your parents say you can go out if you clean your room and do your homework? Run the code below and try different values for cleanedRoom and didHomework and see what they have to be for it to print You can go out.

java
public class Test1
{
public static void main(String[] args)
{
boolean cleanedRoom = true;
boolean didHomework = false;
if (cleanedRoom && didHomework)
{
System.out.println("You can go out");
}
else
{
System.out.println("No, you can't go out");
}
}
}

What if it is okay if only one of two things is true? Use || as a logical or to join two Boolean expressions and the body of the condition will be executed if one or both are true.

For example, your parents might say you can go out if you can walk or they don’t need the car. Try different values for walking and carIsAvailable and see what the values have to be to print You can go out.

java
public class Test2
{
public static void main(String[] args)
{
boolean walking = false;
boolean carIsAvailable = false;
if (walking || carIsAvailable)
{
System.out.println("You can go out");
}
else
{
System.out.println("No, you can't go out");
}
}
}

In English, we often use an exclusive-or like in the sentence “do you want to be player 1 or player 2?” where you can’t be both player 1 and player 2. In programming, the or-operator is an inclusive-or which means that the whole expression is true if either one or the other or both conditions are true.

With numerical values, the or (||) operator is often used to check for error conditions on different ends of the number line, while the and (&&) operator is often used to see if a number is in an range.

java
public class TestNum
{
public static void main(String[] args)
{
int score = 10; // Try -10 and 110
if (score < 0 || score > 100)
{
System.out.println("Score has an illegal value.");
}
if (score >= 0 && score <= 100)
{
System.out.println("Score is in the range 0-100");
}
}
}

The not (!) operator can be used to negate a boolean value. We’ve seen ! before in != (not equal).

The code below says if homework is not done, you can’t go out. Try different values for homeworkDone.

java
public class TestNot
{
public static void main(String[] args)
{
boolean homeworkDone = false;
if (!homeworkDone)
{
System.out.println("Sorry, you can't go out!");
}
}
}

In Java, ! will be executed before &&, and && will be executed before ||, unless there are parentheses. Anything inside parentheses is executed first.

The following table (also called a truth table) shows the result for P && Q when P and Q are both expressions that can be true or false. As you can see below the result of P && Q is only true if both P and Q are true.

PQP && Q
truetruetrue
falsetruefalse
truefalse?
falsefalsefalse

The following table shows the result for P || Q when P and Q are both expressions that can be true or false. As you can see below the result of P || Q is true if either P or Q is true. It is also true when both of them are true.

PQP || Q
truetruetrue
falsetrue?
truefalsetrue
falsefalsefalse

3.5.2. Short Circuit Evaluation

Both && and || use short circuit evaluation. That means that the second expression (on the right of the operator) isn’t necessarily checked, if the result from the first expression is enough to tell if the compound boolean expression is true or false:

  • If two boolean values/expressions are combined with a logical or (||) and the first expression is true, then the second expression won’t be executed, since only one needs to be true for the result to be true.

  • If two boolean values/expressions are combined with a logical and (&&) and the first expression is false, then the second expression won’t be executed. If the first expression is false, the result will be false, since both sides of the && need to be true for the result to be true.

What is printed when the following code executes and x has been set to 0 and y to 3?

java
if (x > 0 && (y / x) == 3)
{
System.out.println("first case");
}
else
{
System.out.println("second case");
}

A. first case
B. second case
C. You will get a error because you can't divide by zero.


What is printed when the following code executes and x has been set to zero and y is set to 3?

java
if (x == 0 || (y / x) == 3)
{
System.out.println("first case");
}
else
{
System.out.println("second case");
}

A. first case
B. second case
C. You will get a error because you can't divide by zero.

3.5.3 Summary

  • Logical operators ! (not), && (and), and || (or) are used with Boolean values.

  • A && B is true if both A and B are true.

  • A || B is true if either A or B (or both) are true.

  • !A is true if A is false.

  • In Java, ! has precedence (is executed before) && which has precedence over ||. Parentheses can be used to force the order of execution in a different way.

  • When the result of a logical expression using && or || can be determined by evaluating only the first Boolean operand, the second is not evaluated. This is known as short-circuit evaluation.

3.5.4. AP Practice

Consider the following code segment. What is printed as a result of executing the code segment?

java
int x = 10;
int y = 5;
if (x % 2 == 0 && y % 2 == 0 || x > y)
{
System.out.print("First ");
if (y * 2 == x || y > 5 && x <= 10)
{
System.out.print("Second ");
}
else
{
System.out.print("Third ");
}
}

A. Nothing is printed out.
B. First
C. Third
D. FirstSecond
E. FirstThird

3.6. Equivalent Boolean Expressions (De Morgan’s Laws)

In this lesson, you will learn about De Morgan’s Laws which simplify statements like this. We know that !(a senior at our high school) could mean !(a senior) or !(at our high school). Let’s learn more about De Morgan’s Laws.

3.6.1. De Morgan’s Laws

De Morgan’s Laws were developed by Augustus De Morgan in the 1800s. They show how to simplify the negation of a complex boolean expression, which is when there are multiple expressions joined by an and (&&) or or (||), such as (x < 3) && (y > 2). When you negate one of these complex expressions, you can simplify it by flipping the operators and end up with an equivalent expression. De Morgan’s Laws state the following equivalencies. Here’s an easy way to remember De Morgan’s Laws: move the NOT inside, AND becomes OR and move the NOT inside, OR becomes AND.

De Morgan’s Laws to simplify complex expressions
De Morgan’s Laws to simplify complex expressions

In Java, De Morgan’s Laws are written with the following operators:

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

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

You can also simplify negated boolean expressions that have relational operators like <, >, ==. You can move the negation inside the parentheses by flipping the relational operator to its opposite sign. For example, not (c equals d) is the same as saying c does not equal d. An easy way to remember this is To move the NOT, flip the sign. Notice that == becomes !=, but < becomes >=, > becomes <=, <= becomes >, and >= becomes < where the sign is flipped and an equal sign may also be added or removed.

  • !(c == d) is equivalent to c != d

  • !(c != d) is equivalent to c == d

  • !(c < d) is equivalent to c >= d

  • !(c > d) is equivalent to c <= d

  • !(c <= d) is equivalent to c > d

  • !(c >= d) is equivalent to c < d

3.6.2. Truth Tables

Although you do not have to memorize De Morgan’s Laws for the CSA Exam, you should be able to show that two boolean expressions are equivalent. One way to do this is by using truth tables. For example, we can show that !(a && b) is equivalent to !a || !b by constructing the truth table below and seeing that they give identical results for the 2 expressions (the last 2 columns in the table below are identical!).

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

3.6.3. Simplifying Boolean Expressions

Often, you can simplify boolean expressions to create equivalent expressions. For example, applying De Morgan’s Laws to !(x < 3 && y > 2) yields !(x < 3) || !(y > 2) as seen in the figure below. This can then be simplified further by flipping the relational operators to remove the not. So, !(x < 3) || !(y > 2) is simplified to (x >= 3 || y <= 2) where the relational operators are flipped and the negation is removed. These two simplification steps are seen below.

An example boolean expression simplified
An example boolean expression simplified

3.6.4. Summary

  • De Morgan’s Laws can be applied to Boolean expressions to create equivalent ones:

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

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

  • A negated expression with a relational operator can be simplified by flipping the relational operator to its opposite sign.

    • !(c == d) is equivalent to c != d

    • !(c != d) is equivalent to c == d

    • !(c < d) is equivalent to c >= d

    • !(c > d) is equivalent to c <= d

    • !(c <= d) is equivalent to c > d

    • !(c >= d) is equivalent to c < d

  • Truth tables can be used to prove that 2 Boolean expressions are identical.

  • Equivalent Boolean expressions will evaluate to the same value in all cases.

3.6.5. AP Practice

Which of the following best describes the value of the Boolean expression: a && !(b || a)

A. The value is always true.
B. The value is always false.
C. The value is true when a has the value false, and is false otherwise.
D. The value is true when b has the value false, and is false otherwise.
E. The value is true when either a or b has the value true, and is false otherwise.

3.7. Comparing Objects

Comparing objects is a little different than comparing primitive typed values like numbers. Objects can be very complex and have many attribute values or instance variables inside them. In this lesson, we will take a look at String objects and the difference between comparing them with == vs. the equals method.

3.7.1. String Equality

The equals method for Strings compares two strings letter by letter. s1.equals(s2) is true if s1 and s2 have all the same characters in the same order. With Strings and other objects, you almost always use equals instead of == to check their equality.

When the operator == is used to compare object variables, it returns true when the two variables refer to the same object. These variables are called object references and aliases for the same object. With strings this happens when one string variable is set to another.

String aliases
String aliases

java
public class Test1
{
public static void main(String[] args)
{
String s1 = new String("Hello");
String s2 = new String("Bye");
String s3 = s2; // s3 is now an alias for s2
System.out.println(s3);
System.out.println(s2 == s3);
System.out.println(s2.equals(s3));
}
}

Here’s the representation of memory where s2 and s3 refer to the same String object.

[

s2 and s3 are aliases referring to the same String object)
s2 and s3 are aliases referring to the same String object)

3.7.2. Equality with New Strings

If you use the new keyword to create a string, it will always create a new string object. So, even if we create two string objects with new that contain all the same characters in the same order, they will not refer to the same object.

java
public class Test2
{
public static void main(String[] args)
{
String s1 = new String("Hello");
String s2 = new String("Hello");
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
}
}

Here is the representation of these String objects in memory.

Two strings that are equal with equals but not with ==.
Two strings that are equal with equals but not with ==.

Note that you can also create Strings using string literals instead of new, like String s = "Hello". String literals behave a little differently because they are re-used if they already exist instead of creating a new object. But you should not see questions with string literals and == on the AP exam.

Only use == with primitive types like int or to test if two strings (or objects) refer to the same object. Use equals, not ==, with strings to test if they are equal letter by letter.

3.7.3. Comparing with null

One common place to use == or != with objects is to compare them to null to see if they really exist. Sometimes short-circuit evaluation is used to avoid an error if the object doesn’t exist. Remember that short-circuit evaluation is used with && in Java meaning that if the first part of the if condition is false, it doesn’t even have to check the second condition and it knows the whole && test is false.

Try the following code to see a NullPointerException (if you don’t see the exception because of the autograding, you can copy it into the pencil icon scratch area to run it without the grader). Since s is null, trying to access indexOf on s throws an NullPointerException. Comment out the first if statement and run the program again. The second if statement avoids the error with shortcircuit evaluation. Because s != null is false, the rest of the Boolean expression is not evaluated. Now, change s to set it to "apple" instead of null in the first line and run the code again to see that the if statements can print out that “apple contains an a”.

java
public class NullTest
{
public static void main(String[] args)
{
String s = null;
if (s.indexOf("a") >= 0)
{
System.out.println(s + " contains an a");
}
if (s != null && s.indexOf("a") >= 0)
{
System.out.println(s + " contains an a");
}
}
}

3.7.4. Summary

  • Often classes have their own equals method, which can be used to determine whether two objects of the class are equivalent.

  • Two object references are considered aliases when they both reference the same object.

  • Object reference values can be compared, using == and !=, to identify aliases.

  • A reference value can be compared with null, using == or !=, to determine if the reference actually references an object.

3.7.5. AP Practice

Consider the following code segment.

java
String message = new String("AP Practice");
String note = new String("AP Practice");
String memo = new String("memo");
int i = 5;
if (message.equals(note) && !message.equals("memo"))
{
message = note;
if (message == note && message.length() > i)
{
i = 3;
memo = message.substring(i);
}
}

Which of the following expressions evaluate to true after the code segment above executes?

A. message == note && message == memo
B. message.equals(note) && message.equals(memo)
C. message == note && memo.equals(“Practice”)
D. message != note || message == memo
E. message.equals(memo) || memo.equals(note)