Java’s
Selection Statements
Java
supports two selection statements: if
and switch. These statements allow
you to control the flow of your program’s execution based upon conditions known
only during run time. You will be pleasantly surprised by the power and
flexibility contained in these two statements.
if
The if statement was introduced in Chapter
2. It is examined in detail here. The if
statement is Java’s conditional branch statement. It can be used to route
program execution through two different paths. Here is the general form of the if statement:
if (condition) statement1; else statement2;
Here,
each statement may be a single
statement or a compound statement enclosed in curly braces (that is, a block). The condition is any expression that returns a boolean value. The else clause
is optional.
The if works like this: If the condition is true, then statement1 is executed. Otherwise, statement2 (if it exists) is executed.
In no case will both statements be executed. For example, consider the following:
int a, b;
//...
if(a < b) a = 0;
else b = 0; 81
Here, if
a is less than b, then a is set to
zero. Otherwise, b is set to zero.
In no case are they both set to zero.
Most
often, the expression used to control the if
will involve the relational operators. However, this is not technically
necessary. It is possible to control the if
using a single boolean variable, as
shown in this code fragment:
boolean dataAvailable; //...
if (dataAvailable)
ProcessData();
else waitForMoreData();
Remember,
only one statement can appear directly after the if or the else. If you
want to include more statements, you’ll need to create a block, as in this
fragment:
int bytesAvailable; // ...
if (bytesAvailable > 0) {
ProcessData(); bytesAvailable -= n;
} else waitForMoreData();
Here,
both statements within the if block
will execute if bytesAvailable is
greater than zero. Some programmers find it convenient to include the curly
braces when using the if, even
when
there is only one statement in each clause. This makes it easy to add another
statement at a later date, and you don’t have to worry about forgetting the
braces. In fact, forgetting to define a block when one is needed is a common
cause of errors. For example, consider the following code fragment:
int bytesAvailable; // ...
if (bytesAvailable > 0) {
ProcessData(); bytesAvailable -= n;
} else waitForMoreData();
bytesAvailable = n;
It seems clear that the
statement bytesAvailable = n; was
intended to be executed inside the else clause,
because of the indentation level. However, as you recall, whitespace is
insignificant to Java, and there is
no way for the compiler to know what was intended. This code will compile
without complaint, but it will behave incorrectly when run. The preceding
example
is fixed in the code that
follows:
int bytesAvailable; // ...
if (bytesAvailable > 0) {
ProcessData(); bytesAvailable -= n;
} else {
waitForMoreData();
bytesAvailable = n;
}
Nested
ifs
A nested if is an if statement that is the target of
another if or else. Nested ifs are
very common in programming. When you nest ifs,
the main thing to remember is that an else
statement always refers to the nearest if
statement that is within the same block as the else and that is not already associated with an else. Here is an example:
if(i == 10) {
if(j < 20) a = b;
if(k > 100) c = d; // this
if is
else a = c; // associated with this else
}
else a = d; // this else refers to if(i == 10)
As the
comments indicate, the final else is
not associated with if(j<20)
because it is not in the same block (even though it is the nearest if without an else). Rather, the final else
is associated with if(i==10). The
inner else refers to if(k>100) because it is the closest if within the same block.
The
if-else-if Ladder
A common
programming construct that is based upon a sequence of nested ifs is the if-else-if ladder. It looks like this:
if(condition) statement;
else if(condition) statement;
else if(condition) statement;
.
.
.
else statement;
The if statements are executed from the top down. As soon as one of the
conditions controlling the if is true, the statement associated with
that if is executed, and the rest of
the ladder is bypassed. If none of the conditions is true, then the final else statement will be executed. The
final else acts as a default
condition; that is, if all other conditional tests fail, then the last else statement is performed. If there
is no final else and all other
conditions are false, then no action
will take place.
Here is
a program that uses an if-else-if
ladder to determine which season a particular month is in.
// Demonstrate if-else-if statements.
class IfElse {
public static void
main(String args[]) { int month = 4; // April
String season;
if(month == 12 || month == 1
|| month == 2) season = "Winter";
else if(month == 3 || month
== 4 || month == 5) season = "Spring";
else if(month == 6 || month
== 7 || month == 8) season = "Summer";
else if(month == 9 || month
== 10 || month == 11) season = "Autumn";
else
season = "Bogus Month";
System.out.println("April is in the "
+ season + ".");
}
}
Here is the output produced
by the program:
April is in the Spring.
You
might want to experiment with this program before moving on. As you will find,
no matter what value you give month,
one and only one assignment statement within the ladder will be executed.
switch
The switch statement is Java’s multiway branch statement. It provides
an easy way to dispatch execution to different parts of your code based on the
value of an expression. As such, it often provides a better alternative than a
large series of if-else-if
statements. Here is the general form of a switch
statement:
switch (expression) { case value1:
//
statement sequence break;
case value2:
//
statement sequence break;
.
.
.
case valueN :
//
statement sequence break;
default:
// default statement sequence
}
For
versions of Java prior to JDK 7, expression
must be of type byte, short, int, char, or an
enumeration. (Enumerations are described in Chapter 12.) Beginning with JDK 7, expression can also be of type String. Each value specified in the case statements must be a unique
constant expression (such as a literal value). Duplicate case values are not allowed. The type of each value must be compatible
with the type of expression.
The switch statement works like this: The value of the expression is
compared with each of the values in the case
statements. If a match is found, the code sequence following that case statement is executed. If none of
the constants matches the value of the expression, then the default statement is executed. However,
the default statement is optional.
If no case matches and no default is present, then no further action is taken.
The break statement is used inside the switch to terminate a statement
sequence. When a break statement is
encountered, execution branches to the first line of code that follows the entire switch statement. This has the effect of “jumping out” of the switch.
Here is a simple example that
uses a switch statement:
// A simple example of the switch.
class SampleSwitch {
public static void
main(String args[]) { for(int i=0; i<6; i++)
switch(i) { case 0:
System.out.println("i is
zero."); break;
case 1:
System.out.println("i is
one."); break;
case 2:
System.out.println("i is two.");
break;
case 3:
System.out.println("i is three.");
break;
default:
System.out.println("i is greater than
3.");
}
}
}
The output produced by this
program is shown here:
i is zero. i is one. i is two. i is three.
i is greater than 3. i is greater than 3.
As you can see, each time
through the loop, the statements associated with the case constant that matches i
are executed. All others are bypassed. After i is greater than 3, no case
statements match, so the default
statement is executed.
The break statement is optional. If you omit the break, execution will continue on into the next case. It is sometimes desirable to have
multiple cases without break statements between them. For
example, consider the following program:
// In a switch, break statements are optional.
class MissingBreak {
public static void main(String args[]) {
for(int i=0; i<12; i++)
switch(i) { case 0: case 1: case 2: case 3:
case 4:
System.out.println("i is less than
5"); break;
case 5: case 6: case 7: case 8: case 9:
System.out.println("i is less than
10"); break;
default:
System.out.println("i is 10 or
more");
}
}
}
This program generates the
following output:
i is less than 5 i is less than 5 i is less
than 5 i is less than 5 i is less than 5 i is less than 10 i is less than 10 i
is less than 10 i is less than 10 i is less than 10 i is 10 or more
i is 10 or more
As you
can see, execution falls through each case
until a break statement (or the end
of the switch) is reached.
While the preceding example
is, of course, contrived for the sake of illustration, omitting the break statement has many practical
applications in real programs. To sample its more realistic usage, consider the
following rewrite of the season example shown earlier. This version uses a switch to provide a more efficient
implementation.
// An improved version of the season program.
class Switch {
public static void main(String args[]) { int
month = 4;
String season;
switch (month) {
case 12:
case 1:
case 2:
season = "Winter";
break;
case 3:
case 4:
case 5:
season = "Spring";
break;
case 6:
case 7:
case 8:
season = "Summer";
break;
case 9:
case 10:
case 11:
season = "Autumn";
break;
default:
season = "Bogus Month";
}
System.out.println("April is in the "
+ season + ".");
}
}
As mentioned, beginning with
JDK 7, you can use a string to control a switch
statement. For example,
// Use a string to control a switch statement.
class StringSwitch {
public static void main(String args[]) {
String str = "two";
switch(str) { case
"one":
System.out.println("one");
break; case "two":
System.out.println("two");
break;
case "three":
System.out.println("three"); break;
default:
System.out.println("no
match"); break;
}
}
}
As you would expect, the output
from the program is
two
The string contained in str (which is "two" in this
program) is tested against the case
constants. When a match is found (as it is in the second case), the code sequence associated with that sequence is executed.
Being
able to use strings in a switch
statement streamlines many situations. For example, using a string-based switch is an improvement over using the
equivalent sequence of if/else
statements. However, switching on strings can be more expensive than switching
on integers. Therefore, it is best to switch on strings only in cases in which
the controlling data is already in string form. In other words, don’t use
strings in a switch unnecessarily.
Nested
switch Statements
You can
use a switch as part of the
statement sequence of an outer switch.
This is called a nested switch. Since a switch statement defines its own block, no
conflicts arise between the case constants in the inner switch and those in the outer switch. For example, the following fragment is perfectly valid:
switch(count) { case 1:
switch(target) { // nested
switch case 0:
System.out.println("target
is zero"); break;
case 1: // no conflicts with outer switch
System.out.println("target is one"); break;
}
break;
case 2: // ...
Here,
the case 1: statement in the inner
switch does not conflict with the case
1: statement in the outer switch. The count
variable is compared only with the list of cases at the outer level. If count is 1, then target is compared with the inner list cases.
In summary, there are three
important features of the switch
statement to note:
The switch differs from the if
in that switch can only test for
equality, whereas if can evaluate
any type of Boolean expression. That is, the switch looks only for a match between the value of the expression
and one of its case constants.
No two case constants in the same switch
can have identical values. Of course, a switch
statement and an enclosing outer
switch can have case constants
in common.
A switch statement is usually more efficient than a set of nested ifs.
The last point is
particularly interesting because it gives insight into how the Java compiler
works. When it compiles a switch
statement, the Java compiler will inspect each of the case constants and create a “jump table” that it will use for
selecting the path of execution depending on the value of the expression.
Therefore, if you need to select among a large group of values, a switch statement will run much faster
than the equivalent logic coded using a sequence of if-elses. The compiler can do this because it knows that the case constants are all the same type
and simply must be compared for equality with the switch expression. The compiler has no such knowledge of a long
list of if expressions.
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.