by Laura Lemay
Although you could write Java programs using what you've learned so far, those programs would be pretty dull. Much of the good stuff in Java or in any programming language results when you have arrays to store values in and control-flow constructs (loops and conditionals) to execute different bits of a program based on tests. Today, you'll find out about the following:
Arrays in Java, as in other languages, are a way to store collections
of items into a single unit. The array has some number of slots,
each of which holds an individual item. You can add and delete
items to those slots as needed. Unlike in other languages, however,
arrays in Java are actual objects that can be passed around and
treated just like other objects.
New Time |
An array is a collection of items. Each slot in the array can hold an object or a primitive value. Arrays in Java are objects that can be treated just like other objects in the language. |
Arrays can contain any type of element value (primitive types or objects), but you can't store different types in a single array. You can have an array of integers or an array of strings or an array of arrays, but you can't have an array that contains, for example, both strings and integers.
To create an array in Java, you use three steps:
The first step in creating an array is creating a variable that will hold the array, just as you would any other variable. Array variables indicate the type of object the array will hold (just as they do for any variable) and the name of the array, followed by empty brackets ([]). The following are all typical array variable declarations:
String difficultWords[]; Point hits[]; int temps[];
An alternate method of defining an array variable is to put the brackets after the type instead of after the variable. They are equivalent, but this latter form is often much more readable. So, for example, these three declarations could be written like this:
String[] difficultWords; Point[] hits; int[] temps;
The second step is to create an array object and assign it to that variable. There are two ways to do this:
The first way is to use the new operator to create a new instance of an array:
String[] names = new String[10];
That line creates a new array of Strings with 10 slots (sometimes called elements). When you create a new array object using new, you must indicate how many slots that array will hold. This line does not put actual String objects in the slots-you'll have to do that later.
Array objects can contain primitive types such as integers or booleans, just as they can contain objects:
int[] temps = new int[99];
When you create an array object using new, all its slots are initialized for you (0 for numeric arrays, false for boolean, '\0' for character arrays, and null for objects). You can then assign actual values or objects to the slots in that array. You can also create an array and initialize its contents at the same time. Instead of using new to create the new array object, enclose the elements of the array inside braces, separated by commas:
String[] chiles = { "jalapeno", "anaheim", "serrano", "habanero", "thai" };
Technical Note |
Note that the Java keyword null refers to a null object (and can be used for any object reference). It is not equivalent to zero or the '\0' character as the NULL constant is in C. |
Each of the elements inside the braces must be of the same type and must be the same type as the variable that holds that array (the Java compiler will complain if they're not). An array the size of the number of elements you've included will be automatically created for you. This example creates an array of String objects named chiles that contains five elements.
Once you have an array with initial values, you can test and change the values in each slot of that array. To get at a value stored within an array, use the array subscript expression ([]):
myArray[subscript];
The myArray part of this expression is a variable holding an array object, although it can also be an expression that results in an array. The subscript part of the expression, inside the brackets, specifies the number of the slot within the array to access. Array subscripts start with 0, as they do in C and C++. So, an array with 10 elements has 10 array slots accessed using subscript 0 to 9.
Note that all array subscripts are checked when your Java program is run to make sure that they are inside the boundaries of the array (greater than or equal to 0 but less than the array's length). Unlike in C, it is impossible in Java to access or assign a value to an array slot outside the boundaries of the array (thereby avoiding a lot of the common problems and bugs that result from overrunning the bounds of an array in C-like languages). Note the following two statements, for example:
String[] arr = new String[10]; arr[10] = "eggplant";
A program with that last statement in it produces an error at that line when you try to run it. (Actually, to be more technically correct, it throws an exception. You'll learn more about exceptions on Day 18, "Multithreading.") The array stored in arr has only 10 slots numbered from 0, the element at subscript 10 doesn't exist.
If the array subscript is calculated at runtime (for example, as part of a loop) and ends up outside the boundaries of the array, the Java interpreter also produces an error.
How can you keep from accidentally overrunning the end of an array in your own programs? You can test for the length of the array in your programs using the length instance variable-it's available for all array objects, regardless of type:
int len = arr.length // returns 10
However, just to reiterate: The length of the array is 10, but its subscript can only go up to 9. Arrays start numbering from 0. Whenever you work with arrays, keep this in mind and subtract 1 from the length of the array to get its largest element.
To assign an element value to a particular array slot, merely put an assignment statement after the array access expression:
myarray[1] = 15; sentence[0] = "The"; sentence[10] = sentence[0];
An important thing to note is that an array of objects in Java is an array of references to those objects (similar in some ways to an array of pointers in C or C++). When you assign a value to a slot in an array, you're creating a reference to that object, just as you do for a plain variable. When you move values around inside arrays (as in that last line), you just reassign the reference; you don't copy the value from one slot to another. Arrays of primitive types such as ints or floats do copy the values from one slot to another.
Arrays of references to objects, as opposed to the objects themselves, are particularly useful because you can have multiple references to the same objects both inside and outside arrays. For example, you can assign an object contained in an array to a variable and refer to that same object by using either the variable or the array position.
Got it? Arrays are pretty simple to create and modify, but they provide an enormous amount of functionality for Java. You'll find yourself running into arrays a lot the more you use Java.
To finish up the discussion on arrays, here's a simple program that shows how to create, initialize, modify, and examine parts of an array. Listing 5.1 has the code.
Listing 5.1. Various simple array operations.
1: class ArrayTest { 2: 3: String[] firstNames = { "Dennis", "Grace", "Bjarne", "James" }; 4: String[] lastNames = new String[firstNames.length]; 5: 6: void printNames() { 7: int i = 0; 8: System.out.println(firstNames[i] 9: + " " + lastNames[i]); 10: i++; 11: System.out.println(firstNames[i] 12: + " " + lastNames[i]); 13: i++; 14: System.out.println(firstNames[i] 15: + " " + lastNames[i]); 16: i++; 17: System.out.println(firstNames[i] 18: + " " + lastNames[i]); 19: } 20: 21: public static void main (String args[]) { 22: ArrayTest a = new ArrayTest(); 23: a.printNames(); 24: System.out.println("----------"); 25: a.lastNames[0] = "Ritchie"; 26: a.lastNames[1] = "Hopper"; 27: a.lastNames[2] = "Stroustrup"; 28: a.lastNames[3] = "Gosling"; 29: a.printNames(); 30: } 31:}
The ArrayTest class also
has two methods: printNames()
and main(). printNames(),
defined in lines 6 through 19, is a utility method that does nothing
but go through the firstNames
and lastNames arrays sequentially,
printing the values of each slot, one name per line. Note that
the array index we've defined here (i)
is initially set to 0 because
Java array slots all start numbering from 0.
Finally, there is main(),
which performs the actual actions of this example. The main()
method here does four things:
One other note I should make about Listing 5.1 is that it's a
terrible example of programming style. Usually when you deal with
arrays you do not hard code the number of elements into the code
as we have here; instead you use a loop to go through each element
of the array in turn. This makes the code a lot shorter and, in
many cases, easier to read. You'll learn about loops later in
this section, and we'll rewrite this example so that it works
more flexibly.
One last thing to note about arrays before we move on to the rest
of this lesson is about multidimensional arrays. Java does not
directly support multidimensional arrays. However, you can declare
and create an array of arrays (and those arrays can contain arrays,
and so on, for however many dimensions you need) and access the
arrays as you would C-style multidimensional arrays:
Before we launch into the last two-thirds of this lesson, let's
take a small detour into a topic I haven't mentioned a whole lot
up to this point (but that will be important later on): block
statements.
A block statement is simply a group of Java statements surrounded
by braces ({}). You've seen
blocks a whole lot already; you've used a block statement to contain
the variables and methods in a class definition, and inside that
block you've also used blocks to hold the body of a method definition.
The opening brace opens the block, and the closing brace closes
the nearest closing block. Easy, right?
You can also use blocks even further, inside method definitions.
The rule is that you can use a block anywhere a single statement
would go. Each statement inside the block is then executed sequentially.
So what's the difference between using a group of individual statements
and using a block? The block creates a new local variable scope
for the statements inside it. This means that you can declare
and use local variables inside a block, and those variables will
cease to exist after the block is finished executing. For example,
here's a block inside a method definition that declares a new
variable y. You cannot use
y outside the block in which
it's declared:
Blocks are not usually used in this way-alone in a method definition,
with random variable declarations inside them. You've mostly seen
blocks up to this point surrounding class and method definitions,
but another very common use of block statements is in the control
flow constructs you'll learn about in the remainder of today's
lesson.
The if conditional statement
is used when you want to execute different bits of code based
on a simple test. if conditions
are nearly identical to if
statements in C: They contain the keyword if,
followed by a boolean test, followed by either a single statement
or a block statement to execute if the test is true.
Here's a simple example that prints the message x
is smaller than y only if the value of x
is less than the value of y:
An optional else keyword
provides the alternative statement to execute if the test is false:
Using if, you can only include
a single statement as the code to execute after the test (in this
case, the System.out.println()
method for each one). But because a block can appear anywhere
a single statement can, if you want to do more than just one thing
(as you usually will), you can enclose those statements inside
a block:
This example uses the test (engineState
== true). For boolean tests of this type, a common
shortcut is merely to include the first part of the expression
rather than explicitly test its value against true
or false. Because it's a
boolean variable, it automatically returns true
or false all by itself, so
you don't have to explicitly test it for that value. Here's a
shorter version of the previous code, with the test replaced with
the shorthand version:
Listing 5.2 shows another simple example-this one in full application
form. The Peeper class contains
one utility method called peepMe(),
which tests a value to see if it's even. If it is, it prints Peep!
to the screen.
We'll use a main() method,
as always, in this application to create a new instance of Peeper
and test it, calling the peepMe()
method repeatedly with different values. In the output, only
the values that are even get a Peep!
message.
An alternative to using the if
and else keywords in a conditional
statement is to use the conditional
operator, sometimes called the ternary
operator (ternary
means three; the conditional operator has three parts).
The conditional operator is an expression, meaning that it returns
a value (unlike the more general if,
which can only result in a statement or block being executed).
The conditional operator is most useful for very short or simple
conditionals and looks like this:
test is a boolean
expression that returns true
or false, just like the test
in the if statement. If the
test is true, the conditional
operator returns the value of trueresult;
if it's false, it returns
the value of falseresult.
For example, the following conditional tests the values of x
and y, returns the smaller
of the two, and assigns that value to the variable smaller:
The conditional operator has a very low precedence; that is, it's
usually evaluated only after all its subexpressions are evaluated.
The only operators lower in precedence are the assign-ment operators.
See the precedence chart in Day 3's lesson for a refresher on
precedence of all the operators.
A common programming practice in any language is to test a variable
against some value, and if it doesn't match that value, to test
it again against a different value, and if it doesn't match that
one to make yet another test, and so on until it matches with
the right result. Using only if
statements, this can become unwieldy, depending on how it's formatted
and how many different options you have to test. For example,
you might end up with a set of if
statements something like this or longer:
This form of if statement
is called a nested if
because each else statement
in turn contains yet another if,
and so on, until all possible tests have been made.
Many languages have a shorthand version of the nested if
that is (somewhat) easier to read and allows you to group the
tests and actions. Called a switch
or case statement, in Java
it's called switch and behaves
as it does in C:
In the switch statement,
the test (a variable or expression
that evaluates to a byte,
char, short,
or int) is compared with
each of the case values (valueOne,
valueTwo, and so on) in turn.
If a match is found, the statement (or statements) after the test
is executed. If no match is found, the default
statement is executed. The default
is optional, so if there isn't a match in any of the cases and
default doesn't exist, the
switch statement completes
without doing anything.
Note that the significant limitation of the switch
in Java is that the tests and values can be only simple primitive
types (and then only primitive types that are automatically castable
to int). You cannot use larger
primitive types (long, float),
strings, or other objects within a switch,
nor can you test for any relationship other than simple equality.
This limits the usefulness of switch;
nested ifs can work for any
kind of test on any type.
Here's a simple example of a switch
statement similar to the nested if
shown earlier:
There are two things to be aware of in this example: The first
is that after each case, you can include a single result statement
or as many as you need. Unlike with if,
you don't need to surround multiple statements with braces for
it to work. The second thing to note about this example is the
break statement included
at the end of every case. Without the explicit break, once a match
is made, the statements for that match (and
also all the statements further down in the switch
for all the other cases) are executed until a break
or the end of the switch
is found. In some cases, this may be exactly what you want to
do, but in most cases, you'll want to make sure to include the
break so that only the statements
you want to be executed are actually executed (break, which you'll
learn about in the section "Breaking Out of Loops,"
stops execution at the current point and jumps to the code outside
of the next closing bracket (})).
One handy use of allowing a switch
to continue processing statements after a match is found occurs
when you want multiple values to match to the same statements.
In this instance, you can use multiple case lines with no result,
and the switch will execute
the first statement it finds. For example, in the following switch
statement, the string "x is an even
number." is printed if x
has a value of 2, 4,
6, or 8.
All other values of x print
the string "x is an odd number.":
Listing 5.3 shows yet another example of a switch.
This class, called NumberReader,
converts integer values to their actual English word equivalents
using a method called convertIt().
So where are the break statements?
You don't need them here because you're using return
instead. return is similar
to break except that it breaks
out of the entire method definition and returns a single value.
Again, you'll learn more about this tomorrow when you learn all
about how to define methods.
At this point you've probably seen enough main()
methods to know what's going on, but let's run through this one
quickly.
Line 20 creates a new instance of the NumberReader
class.
Line 21 defines a string called num
that will be the concatenation of the string values of three numbers.
Each number is converted using a call to the convertNum()
method.
Finally, line 22 prints out the result.
The for loop, as in C, repeats
a statement or block of statements until a condition is matched.
for loops are frequently
used for simple iterations in which you repeat a block of statements
a certain number of times and then stop, but you can use for
loops for just about any kind of loop.
The for loop in Java looks
roughly like this:
The start of the for loop
has three parts:
The statement part of the for
loop is the statements that are executed each time the loop iterates.
Just as with if, you can
only include one statement, although a block will work just fine
as well.
Remember the example in the section on arrays where I said that
iterating over the contents of an array is usually done with a
loop? Here's an example of a for
loop that does just that-it initializes all the values of a String
array to null strings:
In this example, the variable I
keeps track of the number of times the loop has occurred; it also
makes a convenient index for the array itself. Here, we start
the for loop with an index
of I. The test for when the
for loop will end is whether
the current index is less than the length of the array (once the
index is bigger than the array, you should stop), and the increment
is simply to add 1 to the index each time. Then, for every loop
you can put a null string ("")
into the array at the given slot.
Any of the parts of the for
loop can be empty statements; that is, you can simply include
a semicolon with no expression or statement, and that part of
the for loop will be ignored.
Note that if you do use a null statement in your for
loop, you may have to initialize or increment any loop variables
or loop indices yourself elsewhere in the program.
You can also have an empty statement for the body of your for
loop, if everything you want to do is in the first line of that
loop. For example, here's one that finds the first prime number
higher than 4000 (it calls a method called notPrime(),
which will theoretically have a way of figuring that out):
Note that a common mistake in C that also occurs in Java is to
accidentally put a semicolon after the first line of the for
loop:
Because the first semicolon ends the loop with an empty statement,
the loop doesn't actually do anything. The println()
function will be printed only once because it's actually outside
the for loop entirely. Be
careful not to make this mistake in your own Java programs.
To finish up for loops, let's
rewrite that example with the names from the array section. The
original example is long and repetitive and only works with an
array four elements long. This version, shown in Listing 5.4,
is shorter and more flexible (but it returns the same output).
Finally, there are while
and do loops. while
and do loops, like for
loops, repeat the execution of a block of Java code until a specific
condition is met. Whether you use a for
loop, a while, or a do
is mostly a matter of your programming style.
while and do
loops are exactly the same as in C and C++ except that their test
conditions must be booleans.
The while loop is used to
repeat a statement or block of statements as long as a particular
condition is true. while
loops look like this:
The condition is a
boolean test because it is in the if
and for
constructions. If the test returns true,
the while loop executes the
statements in bodyOfLoop
and then tests the condition again, repeating until the condition
is false. I've shown the
while loop here with a block
statement because it's most commonly used, although you can use
a single statement in place of the block.
Listing 5.5 shows an example of a while
loop that copies the elements of an array of integers (in array1)
to an array of floats (in
array2), casting each element
to a float as it goes. The
one catch is that if any of the elements in the first array is
0, the loop will immediately
exit at that point.
I've done all the work here in main()
to make things shorter. Here's what's going on here:
Lines 3 and 4, declare the arrays; array1
is an array of ints, which
I've initialized to some suitable numbers. array2,
or floats, is the same length
as array1, but doesn't have
any initial values.
Lines 6 through 10 are for output purposes; they simply iterate
through array1 using a for
loop to print out its values.
Lines 13 through 17 are where the interesting stuff happens. This
bunch of statements both assigns the values of array2
(converting the numbers to floats along the array) and prints
it out at the same time. We start with a count
variable, which keeps track of the array index elements. The test
in the while loop keeps track
of the two conditions for existing the loop, where those two conditions
are running out of elements in array1
or encountering a 0 in array1
(remember, that was part of the original description of what this
program does). We can use the logical conditional &&
to keep track of the test; remember that &&
makes sure both conditions are true
before the entire expression is true.
If either one is false, the
expression returns false
and the loop exits.
So what goes on in this particular example? The output shows that
the first four elements in array1
were copied to array2, but
there was a 0 in the middle
that stopped the loop from going any further. Without the 0,
array2 should end up with
all the same elements as array1.
Note that if the while loop's
test is initially false the
first time it is tested (for example, if the first element in
that first array is 0), the
body of the while loop will
never be executed. If you need to execute the loop at least once,
you can do one of two things:
The do loop is just like
a while loop, except that
do executes a given statement
or block until the condition is false.
The main difference is that while
loops test the condition before looping, making it possible that
the body of the loop will never execute if the condition is false
the first time it's tested. do
loops run the body of the loop at least once before testing the
condition. do loops look
like this:
Here, the bodyOfLoop part
is the statements that are executed with each iteration. It's
shown here with a block statement because it's most commonly used
that way, but you can substitute the braces for a single statement
as you can with the other control-flow constructs. The condition
is a boolean test. If it returns true,
the loop is run again. If it returns false,
the loop exits. Keep in mind that with do
loops, the body of the loop executes at least once.
Listing 5.6 shows a simple example of a do
loop that prints a message each time the loop iterates (10 times,
for this example):
In all the loops (for, while,
and do), the loop ends when
the condition you're testing for is met. What happens if something
odd occurs within the body of the loop and you want to exit the
loop early? For that, you can use the break
and continue keywords.
You've already seen break
as part of the switch statement;
it stops execution of the switch,
and the program continues. The break
keyword, when used with a loop, does the same thing-it immediately
halts execution of the current loop. If you've nested loops within
loops, execution picks up in the next outer loop; otherwise, the
program merely continues executing the next statement after the
loop.
For example, take that while
loop that copied elements from an integer array into an array
of floats until the end of the array or until a 0
is reached. You can instead test for that latter case inside the
body of the while and then
use a break to exit the loop:
continue is similar to break
except that instead of halting execution of the loop entirely,
the loop starts over at the next iteration. For do
and while loops, this means
that the execution of the block starts over again; for for
loops, the increment and test expressions are evaluated and then
the block is executed. continue
is useful when you want to special-case elements within a loop.
With the previous example of copying one array to another, you
can test for whether the current element is 0
and restart the loop if you find it so that the resulting array
will never contain zero. Note that because you're skipping elements
in the first array, you now have to keep track of two different
array counters:
Both break and continue
can have an optional label that tells Java where to break to.
Without a label, break jumps
outside the nearest loop (to an enclosing loop or to the next
statement outside the loop), and continue
restarts the enclosing loop. Using labeled breaks
and continues, you can break
to specific points outside nested loops or continue a loop outside
the current loop.
To use a labeled loop, add the label before the initial part of
the loop, with a colon between them. Then, when you use break
or continue, add the name
of the label after the keyword itself:
In this snippet of code, the label out
labels the outer loop. Then, inside both the for
and the while loops, when
a particular condition is met, a break
causes the execution to break out of both loops and continue executing
any code after both loops.
Here's another example: The program shown in Listing 5.7 contains
a nested for loop. Inside
the innermost loop, if the summed values of the two counters is
greater than 4, both loops exit at once.
As you can see, the loop iterated until the sum of i
and j was greater than 4,
and then both loops exited back to the outer block and the final
message was printed.
Today you have learned about three main topics that you'll most
likely use quite often in your own Java programs: arrays, conditionals,
and loops.
You have learned how to declare an array variable, create and
assign an array object to that variable, and access and change
elements within that array.
Conditionals include the if
and switch statements, with
which you can branch to different parts of your program based
on a boolean test.
Finally, you have learned about the for,
while, and do
loops, each of which enable you to execute a portion of your program
repeatedly until a given condition is met.
Now that you've learned the small stuff, all that's left is to
go over the bigger issues of declaring classes and creating methods
within which instances of those classes can communicate with each
other by calling methods. Get to bed early tonight, because tomorrow
is going to be a wild ride.
So what do you do if an array is full? You have to do it the hard way: Create a new array that's bigger than the initial one and copy all the elements from the old array to the new.
Optionally, you can use a data structure other than an array if you expect to have widely varying numbers of elements in the array. The Vector class, part of the java.util package, is a growable collection you can use in place of an
array.
It's a good idea to declare most of your variables in the outermost block in which they'll be needed-usually at the top of a block statement. The exception might be very simple variables, such as index counters in for loops, where declaring them
in the first line of the for loop is an easy shortcut.
Dennis null
Grace null
Bjarne null
James null
----------
Dennis Ritchie
Grace Hopper
Bjarne Stroustrup
James Gosling
Analysis
This somewhat verbose example shows you how to create and use arrays. The class we've created here, ArrayTest, has two instance variables that hold arrays of String objects. The first, called firstNames, is declared and
initialized in the same line (line 3) to contain four strings. The second instance variable, lastNames, is declared and created in line 4, but no initial values are placed in the slots. Note also that we created the lastNames array to
have exactly the same number of slots as the firstNames array by using the firstNames.length variable as the initial array index. The length instance variable on array objects returns the number of slots in the array.
Note
Who are the people in this example? They're inventors of computer programming languages. Dennis Ritchie is the inventor of C, Bjarne Stroustrup did C++, Grace Hopper is credited with COBOL, and, finally, James Gosling is the principal designer of
Java.
Multidimensional Arrays
int coords[][] = new int[12][12];
coords[0][0] = 1;
coords[0][1] = 2;
Block Statements
New Term
A block statement is a group of individual Java statements enclosed in braces ({}). You can put a block statement anywhere a single statement can go.
void testblock() {
int x = 10;
{ // start of block
int y = 50;
System.out.println("inside the block:");
System.out.println("x:" + x);
System.out.println("y:" + y);
} // end of block
}
if
Conditionals
if (x < y)
System.out.println("x is smaller than y");
if (x < y)
System.out.println("x is smaller than y");
else System.out.println("y is bigger");
New Term
The if conditional executes different bits of code based on the result of a single boolean test.
Technical Note
The difference between if conditionals in Java and C or C++ is that the test must return a boolean value (true or false). Unlike in C, the test cannot return an integer.
if (engineState == true )
System.out.println("Engine is already on.");
else {
System.out.println("Now starting Engine.");
if (gasLevel >= 1)
engineState = true;
else System.out.println("Low on gas! Can't start engine.");
}
if (engineState)
System.out.println("Engine is on.");
else System.out.println("Engine is off.");
Listing 5.2. The Peeper
class.
1: class Peeper {
2:
3: void peepMe(int val) {
4: System.out.println("Value is "
5: + val + ". ");
6: if (val % 2 == 0)
7: System.out.println("Peep!");
8: }
9:
10: public static void main (String args[]) {
11: Peeper p = new Peeper();
12:
13: p.peepMe(1);
14: p.peepMe(2);
15: p.peepMe(54);
16: p.peepMe(77);
17: p.peepMe(1346);
18: }
19: }
Value is 1.
Value is 2.
Peep!
Value is 54.
Peep!
Value is 77.
Value is 1346.
Peep!
Analysis
The heart of the Peeper class is the peepMe() method (lines 3 through 8), where values are tested and an appropriate message is printed. Unlike the methods you've defined in previous examples, note that the definition of peepMe()
includes a single integer argument (see line 3). The peepMe() method starts by printing out the value that was passed to it. Then that argument is tested, using an if conditional, to see if it's an even number. (The modulus test, as
you'll remember from Day 3, "Java Basics," returns the remainder of the division of its operands. So if the remainder of a number divided by 2 is 0, it's an even number.) If the number is even, Peep! is printed
(you'll learn more about defining methods with arguments tomorrow).
The Conditional Operator
test ? trueresult : falseresult;
int smaller = x < y ? x : y;
switch
Conditionals
if (oper == '+')
addargs(arg1, arg2);
else if (oper == '-')
subargs(arg1, arg2);
else if (oper == '*')
multargs(arg1, arg2);
else if (oper == '/')
divargs(arg1, arg2);
switch (test) {
case valueOne:
resultOne;
break;
case valueTwo:
resultTwo;
break;
case valueThree:
resultThree;
break;
...
default: defaultresult;
}
switch (oper) {
case '+':
addargs(arg1, arg2);
break;
case '-':
subargs(arg1, arg2);
break;
case '*':
multargs(arg1, arg2);
break;
case '/':
divargs(arg1, arg2);
break;
}
switch (x) {
case 2:
case 4:
case 6:
case 8:
System.out.println("x is an even number.");
break;
default: System.out.println("x is an odd number.");
}
Listing 5.3. The NumberReader
class.
1: class NumberReader {
2:
3: String convertNum(int val) {
4: switch (val) {
5: case 0: return "zero ";
6: case 1: return "one ";
7: case 2: return "two ";
8: case 3: return "three ";
9: case 4: return "four ";
10: case 5: return "five ";
11: case 6: return "six ";
12: case 7: return "seven ";
13: case 8: return "eight ";
14: case 9: return "nine ";
15: default: return " ";
16: }
17: }
18:
19: public static void main (String args[]) {
20: NumberReader n = new NumberReader();
21: String num = n.convertNum(4) + n.convertNum(1) + n.convertNum(5);
22: System.out.println("415 converts to " + num);
23: }
24:}
415 converts to four one five
Analysis
The heart of this example is, of course, the main switch statement in the middle of the convert Num ( ) method in lines 4 through 16. This switch statement takes the integer argument that was passed into convert Nm ( ) and, when it finds a match, returns
the appropriate string value. (Note that this method is defined to return a string as opposed to the other methods you've defined up to this point, which didn't return anything. You'll learn more about this tomorrow.)
for
Loops
for (initialization; test; increment) {
statements;
}
String strArray[] = new String[10]; \\ the array
int i; // loop index
for (i = 0; i < strArray.length; i++)
strArray[i] = "";
for (i = 4001; notPrime(i); i += 2)
;
for (i = 0; i < 10; i++);
System.out.println("Loop!");
Listing 5.4. A modified array test with loops.
1: class NamesLoop {
2:
3: String[] firstNames = { "Dennis", "Grace", "Bjarne", "James" };
4: String[] lastNames = new String[firstNames.length];
5:
6: void printNames() {
7: for (int i = 0; i < firstNames.length; i++)
8: System.out.println(firstNames[i] + " " + lastNames[i]);
9: }
10:
11: public static void main (String args[]) {
12: ArrayTest a = new ArrayTest();
13: a.printNames();
14: System.out.println("----------");
15: a.lastNames[0] = "Ritchie";
16: a.lastNames[1] = "Hopper";
17: a.lastNames[2] = "Stroustrup";
18: a.lastNames[3] = "Gosling";
19:
20: a.printNames();
21:}
22:}
Dennis null
Grace null
Bjarne null
James null
----------
Dennis Ritchie
Grace Hopper
Bjarne Stroustrup
James Gosling
Analysis
The only difference between this example and Listing 5.1 is in the printNames() method. Instead of going through the array slots one by one, this example uses a for loop to iterate through the array one slot at a time, stopping at the
last element in the array. Using a more general-purpose loop to iterate over an array allows you to use printNames() for any array of any size and still have it print all the elements.
while
and do
Loops
while
Loops
while (condition) {
bodyOfLoop;
}
Listing 5.5. while
loops to copy array elements.
1: class CopyArrayWhile {
2: public static void main (String args[]) {
3: int[] array1 = { 5, 7, 3, 6, 0, 3, 2, 1 };
4: float[] array2 = new float[array1.length];
5:
6: System.out.print("array1: [ ");
7: for (int i = 0; i < array1.length; i++) {
8: System.out.print(array1[i] + " ");
9: }
10: System.out.println("]");
11:
12: System.out.print("array2: [ ");
13: int count = 0;
14: while ( count < array1.length && array1[count] != 0) {
15: array2[count] = (float) array1[count];
16: System.out.print(array2[count++] + " ");
17: }
18: System.out.println("]");
19: }
20:}
array1: [ 5 7 3 6 0 3 2 1 ]
array2: [ 5 7 3 6 ]
do...while
Loops
do {
bodyOfLoop;
} while (condition);
Listing 5.6. A simple do
loop.
1: class DoTest {
2: public static void main (String args[]) {
3: int x = 1;
4:
5: do {
6: System.out.println("Looping, round " + x);
7: x++;
8: } while (x <= 10);
9: }
10: }
Looping, round 1
Looping, round 2
Looping, round 3
Looping, round 4
Looping, round 5
Looping, round 6
Looping, round 7
Looping, round 8
Looping, round 9
Looping, round 10
Breaking Out of Loops
int count = 0;
while (count < array1.length) {
if (array1[count] == 0) {
break;
}
array2[count] = (float) array1[count++];
}
int count1 = 0;
int count2 = 0;
while (count < array1.length) {
if (array1[count1] == 0) {
continue;
count1++
}
array2[count2++] = (float)array1[count1++];
}
Labeled Loops
out:
for (int i = 0; i <10; i++) {
while (x < 50) {
if (i * x == 400)
break out;
...
}
...
}
Listing 5.7. A labeled loop example.
1: class LabelTest {
2: public static void main (String arg[]) {
3:
4: foo:
5: for (int i = 1; i <= 5; i++)
6: for (int j = 1; j <= 3; j++) {
7: System.out.println("i is " + i + ", j is " + j);
8: if (( i + j) > 4)
9: break foo;
10: }
11: System.out.println("end of loops");
12: }
13:}
i is 1, j is 1
i is 1, j is 2
i is 1, j is 3
i is 2, j is 1
i is 2, j is 2
i is 2, j is 3
end of loops
Summary
Q&A
If arrays are objects, and you use new to create them, and they have an instance variable length, where is the Array class? I didn't see it in the Java class
libraries.
Arrays are implemented kind of weirdly in Java. The Array class is constructed automatically when your Java program runs; Array provides the basic framework for arrays,
including the length variable. Additionally, each primitive type and object has an implicit subclass of Array that represents an array of that class or object. When you create a new array object, it may not have an actual class, but it
behaves as if it does.
When you create an array, you have to give it the number of slots that the array has. What happens if you get halfway through your program and you've run out of slots in the array? Does the
array get bigger automatically?
No, arrays stay the same size throughout their existence. And, as I noted in the part of this lesson on arrays, you cannot access slots outside the bounds of the array, so adding extra elements
to a full array will cause an error.
Does Java have gotos?
The Java language defines the keyword goto, but it is not currently used for anything. In other words, no-Java does not have gotos.
I declared a variable inside a block statement for an if. When the if was done, the definition of that variable vanished. Where did it go?
In technical terms, block statements form a new lexical scope. What this means is that if you declare a variable inside a block, it's only visible and usable inside that block. When the block
finishes executing, all the variables you declared go away.
Why can't you use switch with strings?
Strings are objects, and switch in Java works only for the primitive types byte, char, short, and int. To compare strings, you have to use nested
ifs, which enable more general expression tests, including string comparison.
It seems to me that a lot of for loops could be written as while loops, and vice versa.
True. The for loop is actually a special case of while that enables you to iterate a loop a specific number of times. You could just as easily do this with a while
and then increment a counter inside the loop. Either works equally well. This is mostly just a question of programming style and personal choice.