We talked about indentation in the previous chapter. It is a stylistic convention that you really should follow. Although the compiler ignores indentation, inconsistent use of this convention will confuse the people who read your program and likely will cause you to make mistakes. ■
If you want to include more than one statement in each branch, simply enclose the statements in braces { }. Several statements enclosed within braces are considered to be one larger statement. So the following is one large statement that has two smaller statements inside it:
{
System.out.println("Good for you. You earned interest.");
balance = balance + (INTEREST_RATE * balance) / 12;
}
These statements formed by enclosing a list of statements within braces are called compound statements. They are seldom used by themselves but are
if (balance >= 0)
balance = balance + (INTEREST_RATE * balance) / 12;
else
balance = balance - OVERDRAWN_PENALTY;
balance = balance +
(INTEREST_RATE * balance) / 12;
Execute Execute
balance = balance - OVERDRAWN_PENALTY;
True
Start
False Evaluate balance >= 0
FIGURE 3.1 The Action of the if-else Statement in Listing 3.1
Indentation in a program aids readability
LISTING 3.1 A Program Using if-else import java.util.Scanner;
public class BankBalance {
public static final double OVERDRAWN_PENALTY = 8.00;
public static final double INTEREST_RATE = 0.02; //2% annually public static void main(String[] args)
{
double balance;
System.out.print("Enter your checking account balance: $");
Scanner keyboard = new Scanner(System.in);
balance = keyboard.nextDouble();
System.out.println("Original balance $" + balance);
if (balance >= 0) balance = balance + (INTEREST_RATE * balance) / 12;
else balance = balance - OVERDRAWN_PENALTY;
System.out.print("After adjusting for one month ");
System.out.println("of interest and penalties,");
System.out.println("your new balance is $" + balance);
} }
Sample Screen Output 1
Enter your checking account balance: $505.67 Original balance $505.67
After adjusting for one month of interest and penalties, your new balance is $506.51278
Sample Screen Output 2
Enter your checking account balance: $−15.53 Original balance $ −15.53
After adjusting for one month of interest and penalties, your new balance is $ −23.53
often used as substatements of larger statements, such as if-else statements.
The preceding compound statement might occur in an if-else statement such as the following:
if (balance >= 0) {
System.out.println("Good for you. You earned interest.");
balance = balance + (INTEREST_RATE * balance) / 12;
} else {
System.out.println("You will be charged a penalty.");
balance = balance − OVERDRAWN_PENALTY;
}
Notice that compound statements can simplify our description of an if-else
statement. Once we know about compound statements, we can say that every
if-else statement is of the form
if(Boolean_Expression) Statement_1
else
Statement_2
If you want one or both branches to contain several statements instead of just one, use a compound statement for Statement_1 and/or Statement_2. Figure 3.2 summarizes the semantics, or meaning, of an if-else statement.
ExecuteStatement_1 if (Boolean_Expression)
Statement_1 else
Statement_2
ExecuteStatement_2 True
Start
False Evaluate Boolean_Expression
FIGURE 3.2 The Semantics of the if-else Statement
else is optional Braces group multiline actions to form a compound statement
If you omit the else part, the program simply skips Statement when the if
statement’s expression is false, as Figure 3.3 illustrates. For example, if your bank does not charge an overdraft penalty, the statement shown previously would be shortened to the following:
if (balance >= 0) {
System.out.println("Good for you. You earned interest.");
balance = balance + (INTEREST_RATE * balance) / 12;
}
To see how this statement works, let’s give it a little more context by adding some additional statements, as follows, where keyboard is a Scanner
object of the usual sort:
System.out.print("Enter your balance $");
balance = keyboard.nextDouble();
if (balance >= 0) {
System.out.println("Good for you. You earned interest.");
balance = balance + (INTEREST_RATE * balance) / 12;
}
System.out.println("Your new balance is $" + balance);
Executing these statements when your checking account balance is $100 would produce the following interaction:
Enter your balance $100.00
Good for you. You earned interest.
Your new balance is $100.16
Continue with statement afterStatement ExecuteStatement
if (Boolean_Expression) Statement
True
Start
False Evaluate Boolean_Expression
FIGURE 3.3 The Semantics of an if Statement Without an else
if without else either performs an action or does not
Since the expression balance >= 0 is true, you earn some interest. Exactly how much is irrelevant to this example. (However, we used an interest rate of 2 percent per year, as in Listing 3.1.)
Now suppose that your account is overdrawn and has a balance of minus
$50. The output would then be as follows:
Enter your balance $ −50.00 Your new balance is $ −50.00
In this case, the expression balance >= 0 is false, but since there is no else
part, nothing happens—the balance is not changed, and the program simply goes on to the next statement, which is an output statement.
GOTCHA
Secure Programming: Input Validation and Overflow You should check your input to ensure that it is within a valid or reasonable range. For example, consider a program that converts feet to inches. You might write the following:int feet = keyboard.nextInt();
int inches = feet * 12;
This looks perfectly harmless, but what if the user types in unexpected values, either intentionally or by mistake? The result could crash the program or cause unexpected behavior. Some scenarios include:
1. If the user types a negative number for feet then your program might not work correctly with a negative value for inches.
2. If the program is expecting feet to represent the height of a person then there is nothing to stop the user from entering an unreasonable value, like 100 feet.
3. An integer in Java is only able to hold a positive number up to 2,147,483,647. If we try to store a larger number then we get overflow which results in an incorrect value. If the user types a number such as 2,000,000,000 then we multiply it by 12 and get a value that is too large to fit into an integer. When Java encounters an integer value that is too large to fit then it begins to cycle around to the minimum value and continues from there. In this case it results in a negative number for inches,
−1,769,803,776.
We can address these problems with validation to determine that input is in the proper range:
int feet = keyboard.nextInt();
if ((feet >= 0) && (feet < 10)) {
int inches = feet * 12;
. . . }
VideoNote Input validation
RECAP if-else Statements SYNTAX (BASIC FORM)
if (Boolean_Expression) Statement_1
else
Statement_2
If the expression Boolean_Expression is true, Statement_1 is executed;
otherwise, Statement_2 is executed.
EXAMPLE
if (time < limit)
System.out.println("You made it.");
else
System.out.println("You missed the deadline.");
SYNTAX (NO else PART) if (Boolean_Expression) Statement
If the expression Boolean_Expression is true, Statement is executed;
otherwise, Statement is ignored and the program goes on to the next statement.
EXAMPLE
if (weight > ideal)
calorieAllotment = calorieAllotment − 500;
COMPOUND STATEMENT ALTERNATIVES
Each of Statement, Statement_1, and Statement_2 can be a compound statement. If you want to include several statements to be executed for a given branch of the expression, group them between braces, as in the following example:
if (balance >= 0) {
System.out.println("Good for you. You earned interest.");
balance = balance + (INTEREST_RATE * balance) / 12;
} else {
System.out.println("You will be charged a penalty.");
balance = balance – OVERDRAWN_PENALTY;
}
Boolean Expressions
We have already been using simple boolean expressions in if-else statements.
The simplest boolean expressions compare two smaller expressions, as in these examples:
balance >= 0
and
time < limit
Figure 3.4 shows the various Java comparison operators you can use to compare two expressions.
Note that a boolean expression need not begin and end with parentheses.
However, a boolean expression does need to be enclosed in parentheses when it is used in an if-else statement.
GOTCHA
Using = Instead of = = to Test for EqualityThe operator = is the assignment operator. Although this symbol means equality in mathematics, it does not have this meaning in Java. If you write if (x = y) instead of if (x == y) to test whether x and y are equal, you will get
a syntax error message. ■
GOTCHA
Using = = or != to Compare Floating-Point ValuesThe previous chapter warned that floating-point numbers must be thought of as approximations. Numbers that have a fractional part can have an
Name Java Examples
= Equal to == balance == 0
answer == 'y'
≠ Not equal to != income != tax
answer != 'y'
> Greater than > expenses > income
≥ Greater than or equal to >= points >= 60
< Less than < pressure < max
≤ Less than or equal to <= expenses <= income
Math
Notation Java
Notation FIGURE 3.4 Java Comparison Operators
infinite number of digits. Since the computer can store only a limited number of digits in a fraction, floating-point numbers often are not exact.
These approximations can get even less accurate after every operation in a calculation.
Thus, if you compute two floating-point values, they likely will not be exactly equal. Two values that are almost equal might be all you can hope for.
Therefore, you should not use == to compare floating-point numbers. Using the != operator can cause the same problem.
Instead, to test two floating-point numbers for “equality,” you see whether they differ by so little that it could only be due to their approximate nature. If so, you can conclude that they are “close enough” to be considered equal. ■
You can form more complicated boolean expressions from simpler ones by joining them with the logical operator &&, which is the Java version of and. For example, consider the following:
if ((pressure > min) && (pressure < max)) System.out.println("Pressure is OK.");
else
System.out.println("Warning: Pressure is out of range.");
If the value of pressure is greater than min and the value of pressure is less than max, the output will be
Pressure is OK.
Otherwise, the output will be
Warning: Pressure is out of range.
Note that you cannot write
min < pressure < max
Instead, you must express each inequality separately and connect them with
&&, as follows:
(pressure > min) && (pressure < max)
When you form a larger boolean expression by connecting two smaller expressions with &&, the entire larger expression is true only if both of the smaller expressions are true. If at least one of the smaller expressions is false, the larger expression is false. For example,
(pressure > min) && (pressure < max)
is true provided that both (pressure > min) and (pressure < max) are true;
otherwise, the expression is false.
Incorrect!
&& means and
Instead of joining boolean expressions with and, you can join them with or. The Java way of expressing or is ||, which you create by typing two vertical lines. (The symbol | appears on some systems with a gap in the line.) The meaning of the operator || is essentially the same as the English word or. For example, consider
if ((salary > expenses) || (savings > expenses)) System.out.println("Solvent");
else
System.out.println("Bankrupt");
If the value of salary is greater than the value of expenses or the value of
savings is greater than the value of expenses or both are true, then the output will be Solvent; otherwise, the output will be Bankrupt.
RECAP Use && for and
The symbol pair && means and in Java. You can use && to form a larger boolean expression out of two smaller boolean expressions.
SYNTAX
(Sub_Expression_1) && (Sub_Expression_2)
This expression is true if and only if both Sub_Expression_1 and Sub_
Expression_2 are true.
EXAMPLE
if ((pressure > min) && (pressure < max)) System.out.println("Pressure is OK.");
else
System.out.println("Warning: Pressure is out of " + "range.");
RECAP Use || for or
The symbol pair || means or in Java. You can use || to form a larger boolean expression out of two smaller boolean expressions.
SYNTAX
(Sub_Expression_1) || (Sub_Expression_2)
(continued)
|| means or
As we noted earlier, the boolean expression in an if-else statement must be enclosed in parentheses. An if-else statement that uses the && operator is normally parenthesized as follows:
if ((pressure > min) && (pressure < max))
The parentheses in (pressure > min) and in (pressure < max) are not required, but we will normally include them to aid readability. Parentheses are used in expressions containing the operator || in the same way that they are used with &&.
In Java, you can negate a boolean expression by preceding it with !. For example,
if (!(number >= min))
System.out.println("Too small");
else
System.out.println("OK");
If number is not greater than or equal to min, the output will be Too small; otherwise, the output will be OK.
You often can avoid using !, and you should do so when possible. For example, the previous if-else statement is equivalent to
This expression is true if either Sub_Expression_1 or Sub_Expression_2 is true or both are true.
EXAMPLE
if ((salary > expenses) || (savings > expenses)) System.out.println("Solvent");
else
System.out.println("Bankrupt");
<
<=
>
>=
==
!=
>=
>
<=
<
!=
==
! (A Op B) Is Equivalent to (A Op B) FIGURE 3.5 Avoiding the Negation Operator
Parentheses clarify the meaning of a boolean expression
! means negate
if (number < min)
System.out.println("Too small");
else
System.out.println("OK");
Figure 3.5 shows how to transform an expression of the form
!(A Comparison_Operator B)
to one without the negation operator.
If you can avoid using !, your programs should be easier to understand.
However, we will encounter situations that use this operator naturally and clearly. In particular, we can use ! in the context of a loop—which we cover in the next chapter—to negate the value of a boolean variable, which we discuss later in this chapter.
RECAP Use ! for not
The symbol ! means not in Java. You can use ! to negate the value of a boolean expression. Doing so is more common when the expression is a boolean variable. Otherwise, you often can rewrite a boolean expression to avoid negating it.
SYNTAX
!Boolean_Expression
The value of this expression is the opposite of the value of the boolean expression: It is true if Boolean_Expression is false and false if Boolean_
Expression is true.
EXAMPLE
if (!(number < 0))
System.out.println("OK");
else
System.out.println("Negative!");
Figure 3.6 summarizes the three logical operators. Java combines the values of true and false according to the rules given in the chart in Figure 3.7.
For example, if boolean expression A is true, and boolean expression B is false, A && B evaluates to false.
VideoNote Writing boolean expressions
Comparing Strings
To test whether two values of a primitive type—such as two numbers—are equal, you use the equality operator ==. But == has a different meaning when applied to objects. Recall that a string is an object of the class String, so ==
applied to two strings does not test whether the strings are equal. To see whether two strings have equal values, you must use the method equals rather than ==.
For example, the boolean expression s1.equals(s2) returns true if the strings
s1 and s2 have equal values, and returns false otherwise. The program in Listing 3.2 illustrates the use of the method equals. Notice that the two expressions
s1.equals(s2) s2.equals(s1)
are equivalent.
Listing 3.2 also demonstrates the String method equalsIgnoreCase. This method behaves like equals, except that equalsIgnoreCase considers the uppercase and lowercase versions of the same letter to be the same. For example, "Hello" and "hello" are not equal because their first characters, ‘H’
and ‘h’, are different characters. But the method equalsIgnoreCase would consider them equal. For example, the following will display Equal:
if ("Hello".equalsIgnoreCase("hello")) System.out.println("Equal");
Name Java Notation Java Examples
Logicaland && (sum > min) && (sum < max)
Logicalor || (answer == 'y') || (answer == 'Y')
Logicalnot ! !(number < 0)
FIGURE 3.6 Java Logical Operators
Value of A Value of B Value of
A &&B Value of !(A)
true true true true false
true false false true false
false true false true true
false false false false true
Value of A||B
FIGURE 3.7 The Effect of the Boolean Operators && (and), || (or), and ! (not) on Boolean Values
Use the equals method, not ==, to see whether two strings are equal
Notice that it is perfectly valid to use the quoted string "Hello" in the invocation of equalsIgnoreCase. A quoted string is an object of type String
and has all the methods that any other object of type String has.
LISTING 3.2 Testing Strings for Equality
import java.util.Scanner;
public class StringEqualityDemo {
public static void main(String[] args) {
String s1, s2;
System.out.println("Enter two lines of text:");
Scanner keyboard = new Scanner(System.in);
s1 = keyboard.nextLine();
s2 = keyboard.nextLine();
if (s1.equals(s2))
System.out.println("The two lines are equal.");
else
System.out.println("The two lines are not equal.");
if (s2.equals(s1))
System.out.println("The two lines are equal.");
else
System.out.println("The two lines are not equal.");
if (s1.equalsIgnoreCase(s2)) System.out.println(
"But the lines are equal, ignoring case.");
else
System.out.println(
"Lines are not equal, even ignoring case.");
} }
Sample Screen Output Enter two lines of text:
Java is not coffee.
Java is NOT COFFEE.
The two lines are not equal.
The two lines are not equal.
But the lines are equal, ignoring case.
These two invocations of the method equals are equivalent.
GOTCHA
Using == with StringsWhen applied to two strings (or any two objects), the operator == tests whether they are stored in the same memory location. We will discuss that concept in Chapter 5, but for now, we need only realize that == does not test whether two strings have the same values.
For the kinds of applications we consider in this chapter, using == to test for equality of strings can appear to give you the correct answer. However, doing so is a dangerous habit to acquire. You should always use the method
equals rather than == to test strings. Analogous comments apply to the other comparison operators, such as <, and the method compareTo, as you will
soon see. ■
RECAP The Methods equals and equalsIgnoreCase
When testing strings for equality, use either of the methods equals or equalsIgnoreCase.
SYNTAX
String.equals(Other_String)
String.equalsIgnoreCase(Other_String)
EXAMPLE
String s1 = keyboard.next(); //keyboard is a Scanner object if (s1.equals("Hello"))
System.out.println("The string is Hello.");
else
System.out.println("The string is not Hello.");
Programs frequently need to compare two strings to see which is alphabetically before the other. Just as you should not use the == operator to test for equality of strings, you should not use operators such as < and > to test for alphabetic order. Instead you should use the String method compareTo, which we described in Figure 2.5 of Chapter 2.
The method compareTo tests two strings to determine their lexicographic order. Lexicographic order is similar to alphabetic order and is sometimes, but not always, the same as alphabetic order. In lexicographic ordering, the letters and other characters are ordered according to their Unicode sequence, which is shown in the appendix of this book.
Use the compareTo method to compare strings