Chapter 11

Using Arrays to Juggle Values

In This Chapter

arrow Dealing with several values at once

arrow Searching for things

arrow Creating values as you get a program running

Welcome to the Java Motel! No haughty bellhops, no overpriced room service, none of the usual silly puns. Just a clean double room that’s a darn good value!

Getting Your Ducks All in a Row

The Java Motel, with its ten comfortable rooms, sits in a quiet place off the main highway. Aside from a small, separate office, the motel is just one long row of ground floor rooms. Each room is easily accessible from the spacious front parking lot.

Oddly enough, the motel’s rooms are numbered 0 through 9. I could say that the numbering is a fluke — something to do with the builder’s original design plan. But the truth is that starting with 0 makes the examples in this chapter easier to write.

Anyway, you’re trying to keep track of the number of guests in each room. Because you have ten rooms, you may think about declaring ten variables:

  int guestsInRoomNum0, guestsInRoomNum1, guestsInRoomNum2,
   guestsInRoomNum3, guestsInRoomNum4, guestsInRoomNum5,
   guestsInRoomNum6, guestsInRoomNum7, guestsInRoomNum8,
   guestsInRoomNum9;

Doing it this way may seem a bit inefficient — but inefficiency isn’t the only thing wrong with this code. Even more problematic is the fact that you can’t loop through these variables. To read a value for each variable, you have to copy the nextInt method ten times.

  guestsInRoomNum0 = diskScanner.nextInt();
guestsInRoomNum1 = diskScanner.nextInt();
guestsInRoomNum2 = diskScanner.nextInt();
... and so on.

Surely a better way exists.

That better way involves an array. An array is a row of values, like the row of rooms in a one-floor motel. To picture the array, just picture the Java Motel:

  • First, picture the rooms, lined up next to one another.
  • Next, picture the same rooms with their front walls missing. Inside each room you can see a certain number of guests.
  • If you can, forget that the two guests in Room 9 are putting piles of bills into a big briefcase. Ignore the fact that the guests in Room 6 haven’t moved away from the TV set in a day and a half. Instead of all these details, just see numbers. In each room, see a number representing the count of guests in that room. (If free-form visualization isn’t your strong point, look at Figure 11-1.)
    9781118407806-fg1101.tif

    Figure 11-1: An abstract snapshot of rooms in the Java Motel.

In the lingo of this chapter, the entire row of rooms is called an array. Each room in the array is called a component of the array (also known as an array element). Each component has two numbers associated with it:

  • The room number (a number from 0 to 9), which is called an index of the array
  • A number of guests, which is a value stored in a component of the array

Using an array saves you from all the repetitive nonsense in the sample code shown at the beginning of this section. For instance, to declare an array with ten values in it, you can write one fairly short statement:

  int guests[] = new int[10];

If you’re especially verbose, you can expand this statement so that it becomes two separate statements:

  int guests[];
guests = new int[10];

In either of these code snippets, notice the use of the number 10. This number tells the computer to make the guests array have ten components. Each component of the array has a name of its own. The starting component is named guests[0], the next is named guests[1], and so on. The last of the ten components is named guests[9].

remember.eps In creating an array, you always specify the number of components. The array’s indices start with 0 and end with the number that’s one less than the total number of components.

The snippets that I show you give you two ways to create an array. The first way uses one line. The second way uses two lines. If you take the single line route, you can put that line inside or outside a method. The choice is yours. On the other hand, if you use two separate lines, the second line, guests = new int[10], should be inside a method.

tip.eps In an array declaration, you can put the square brackets before or after the variable name. In other words, you can write int guests[] or int[] guests. The computer creates the same guests variable no matter which form you use.

Creating an array in two easy steps

Look once again at the two lines that you can use to create an array:

  int guests[];
guests = new int[10];

Each line serves its own distinct purpose:

  • int guests[]: This first line is a declaration. The declaration reserves the array name (a name like guests) for use in the rest of the program. In the Java Motel metaphor, this line says, “I plan to build a motel here and put a certain number of guests in each room.” (See Figure 11-2.)

    Never mind what the declaration int guests[] actually does. It’s more important to notice what the declaration int guests[] doesn’t do. The declaration doesn’t reserve ten memory locations. Indeed, a declaration like int guests[] doesn’t really create an array. All the declaration does is set up the guests variable. At that point in the code, the guests variable still doesn’t refer to a real array. (In other words, the motel has a name, but the motel hasn’t been built yet.)

  • guests = new int[10]: This second line is an assignment statement. The assignment statement reserves space in the computer’s memory for ten int values. In terms of real estate, this line says, “I’ve finally built the motel. Go ahead and put guests in each room.” (Again, see Figure 11-2.)
9781118407806-fg1102.tif

Figure 11-2: Two steps in creating an array.

Storing values

After you’ve created an array, you can put values into the array’s components. For instance, you would like to store the fact that Room 6 contains 4 guests. To put the value 4 in the component with index 6, you write guests[6] = 4.

Now business starts to pick up. A big bus pulls up to the motel. On the side of the bus is a sign that says “Noah’s Ark.” Out of the bus come 25 couples, each walking, stomping, flying, hopping, or slithering to the motel’s small office. Only 10 of the couples can stay at the Java Motel, but that’s okay because you can send the other 15 couples down the road to the old C-Side Resort and Motor Lodge.

Anyway, to register 10 couples into the Java Motel, you put a couple (2 guests) in each of your 10 rooms. Having created an array, you can take advantage of the array’s indexing and write a for loop, like this:

  for (int roomNum = 0; roomNum < 10; roomNum++) {
   guests[roomNum] = 2;
}

This loop takes the place of ten assignment statements. Notice how the loop’s counter goes from 0 to 9. Compare this with Figure 11-2 and remember that the indices of an array go from 0 to one less than the number of components in the array.

However, given the way the world works, your guests won’t always arrive in neat pairs, and you’ll have to fill each room with a different number of guests. You probably store information about rooms and guests in a database. If you do, you can still loop through an array, gathering numbers of guests as you go. The code to perform such a task may look like this:

  resultset =
    statement.executeQuery("select GUESTS from RoomData");
for (int roomNum = 0; roomNum < 10; roomNum++) {
    resultset.next();
    guests[roomNum] = resultset.getInt("GUESTS");    
}

But because this book doesn’t cover databases until Chapter 17 you may be better off reading numbers of guests from a plain text file. A sample file named GuestList.txt is shown in Figure 11-3.

9781118407806-fg1103.tif

Figure 11-3: The GuestList.txt file.

After you’ve made a file, you can call on the Scanner class to get values from the file. The code is shown in Listing 11-1, and the resulting output is in Figure 11-4.

ontheweb_fmt.eps This book’s website (www.allmycode.com/JavaForDummies) has tips for readers who need to create data files. This includes instructions for Windows, Linux, and Macintosh environments.

Listing 11-1: Filling an Array with Values

  import static java.lang.System.out;
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
public class ShowGuests {
   public static void main(String args[])
                          throws IOException {
      int guests[] = new int[10];
      Scanner diskScanner =
           new Scanner(new File("GuestList.txt"));
      for(int roomNum = 0; roomNum < 10; roomNum++) {
         guests[roomNum] = diskScanner.nextInt();
      }
      out.println("Room Guests");
      for(int roomNum = 0; roomNum < 10; roomNum++) {
         out.print(roomNum);
         out.print(" ");
         out.println(guests[roomNum]);
      }
      diskScanner.close();
   }
}

9781118407806-fg1104.tif

Figure 11-4: Running the code from Listing 11-1.

The code in Listing 11-1 has two for loops. The first loop reads numbers of guests, and the second loop writes numbers of guests.

tip.eps Every array has a built-in length field. An array’s length is the number of components in the array. So, in Listing 11-1, if you print the value of guests.length, you get 10.

Tab stops and other special things

In Listing 11-1, some calls to print and println use the escape sequence. It’s called an escape sequence because you escape from displaying the letter t on the screen. Instead, the characters stand for a tab. The computer moves forward to the next tab stop before printing any more characters. Java has a few of these handy escape sequences. Some of them are shown in Table 11-1.

Table 11-1 Escape Sequences

Sequence

Meaning



backspace

horizontal tab

line feed

f

form feed

carriage return

"

double quote ”

'

single quote '

\

backslash

Using an array initializer

Besides what you see in Listing 11-1, you have another way to fill an array in Java — with an array initializer. When you use an array initializer, you don’t even have to tell the computer how many components the array has. The computer figures this out for you.

Listing 11-2 shows a new version of the code to fill an array. The program’s output is the same as the output of Listing 11-1. (It’s the stuff shown in Figure 11-4.) The only difference between Listings 11-1 and 111-2 is the bold text in Listing 11-2. That bold doodad is an array initializer.

Listing 11-2: Using an Array Initializer

  import static java.lang.System.out;
public class ShowGuests {

   public static void main(String args[]) {
   
      int guests[] = {1, 4, 2, 0, 2, 1, 4, 3, 0, 2};
      out.println("Room Guests");
      
      for (int roomNum = 0; roomNum < 10; roomNum++) {
         out.print(roomNum);
         out.print(" ");
         out.println(guests[roomNum]);
      }
   }
}

tip.eps An array initializer can contain expressions as well as literals. In plain English, this means that you can put all kinds of things between the commas in the initializer. For instance, an initializer like {1 + 3, keyboard.nextInt(), 2, 0, 2, 1, 4, 3, 0, 2} works just fine.

Stepping through an array with the enhanced for loop

Java has an enhanced for loop — a for loop that doesn’t use counters or indices. Listing 11-3 shows you how to do it.

warning.eps The material in this section applies to Java 5.0 and later Java versions. But this section’s material doesn’t work with older versions of Java — versions such as 1.3, 1.4, and so on. For a bit more about Java’s version numbers, see Chapter 2.

Listing 11-3: Get a Load o’ That for Loop!

  import static java.lang.System.out;
public class ShowGuests {
   public static void main(String args[]) {
      int guests[] = {1, 4, 2, 0, 2, 1, 4, 3, 0, 2};
      int roomNum = 0;
      out.println("Room Guests");
      for (int numGuests : guests) {
         out.print(roomNum++);
         out.print(" ");
         out.println(numGuests);
      }
   }
}

Listings 11-1 and 11-2 have the same output. It’s in Figure 11-4.

If you look at the loop in Listing 11-3, you see the same old pattern. Just like the loops in Listing 6-5, this example’s loop has three parts:

  for (variable-type variable-name : range-of-values)

The first two parts are variable-type and variable-name. The loop in Listing 11-3 defines a variable named numGuests, and numGuests has type int. During each loop iteration, the variable numGuests takes on a new value. Look at Figure 11-4 to see these values. The initial value is 1. The next value is 4. After that comes 2. And so on.

Where is the loop finding all these numbers? The answer lies in the loop’s range-of-values. In Listing 11-3, the loop’s range-of-values is guests. So, during the initial loop iteration, the value of numGuests is guests[0] (which is 1). During the next iteration, the value of numGuests is guests[1] (which is 4). After that comes guests[2] (which is 2). And so on.

warning.eps Java's enhanced for loop requires a word of caution. Each time through the loop, the variable that steps through the range of values stores a copy of the value in the original range. The variable does not point to the range itself.

So for example, if you add an assignment statement that changes the value of numGuests in Listing 11-3, this statement has no effect on any of the values stored in the guests array. To drive this point home, imagine that business is bad and I’ve filled my hotel’s guests array with zeros. Then I execute the following code:

  for (int numGuests : guests) {
   numGuests += 1;
   out.print(numGuests + " ");
}
out.println();
for (int numGuests : guests) {
   out.print(numGuests + " ");
}

The numGuests variable takes on values stored in the guests array. But the numGuests += 1 statement doesn’t change the values stored in this guests array. The code’s output looks like this:

  1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0

Searching

You’re sitting behind the desk at the Java Motel. Look! Here comes a party of five. These people want a room, so you need software that checks whether a room is vacant. If one is, the software modifies the GuestList.txt file (refer to Figure 11-3) by replacing the number 0 with the number 5. As luck would have it, the software is right on your hard drive. The software is shown in Listing 11-4.

Listing 11-4: Do You Have a Room?

  import static java.lang.System.out;
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
public class FindVacancy {
   
   public static void main(String args[])
                          throws IOException {
      int guests[] = new int[10];
      int roomNum;
      
      Scanner diskScanner =
         new Scanner(new File("GuestList.txt"));
      for (roomNum = 0; roomNum < 10; roomNum++) {
         guests[roomNum] = diskScanner.nextInt();
      }
      diskScanner.close();
      roomNum = 0;
      while (roomNum < 10 && guests[roomNum] != 0) {
         roomNum++;
      }
      if (roomNum == 10) {
         out.println("Sorry, no vacancy");
      } else {
         out.print("How many people for room ");
         out.print(roomNum);
         out.print("? ");         
         Scanner keyboard = new Scanner(System.in);
         guests[roomNum] = keyboard.nextInt();
         keyboard.close();
         
         PrintStream listOut =
            new PrintStream("GuestList.txt");
         for (roomNum = 0; roomNum < 10; roomNum++) {
            listOut.print(guests[roomNum]);
            listOut.print(" ");
         }
         listOut.close();
      }
   }
}

Figures 11-5 through 11-7 show the running of the code in Listing 11-4. Back in Figure 11-3, the motel starts with two vacant rooms — Rooms 3 and 8. (Remember, the rooms start with Room 0.) The first time that you run the code in Listing 11-4, the program tells you that Room 3 is vacant and puts five people into the room. The second time you run the code, the program finds the remaining vacant room (Room 8) and puts a party of ten in the room. (What a party!) The third time you run the code, you don’t have any more vacant rooms. When the program discovers this, it displays the message Sorry, no vacancy, omitting at least one letter in the tradition of all motel neon signs.

9781118407806-fg1105.tif

Figure 11-5: Filling a vacancy.

9781118407806-fg1106.tif

Figure 11-6: Filling the last vacant room.

9781118407806-fg1107.tif

Figure 11-7: Sorry, Bud. No rooms.

warning.eps A run of the code in Listing 11-4 writes a brand-new GuestList.txt file. This can be confusing because each Java IDE has its own way of displaying the GuestList.txt file’s content. Some IDEs don’t automatically display the newest GuestList.txt file, so after running the code from Listing 11-4, you may not immediately see a change. (For example, in Figure 11-5, Room 3 is empty. But after a run of the code, Figure 11-6 shows Room 3 having five guests.) Even if you don’t see a change, consecutive runs of Listing 11-4 change the GuestList.txt file. Poke around within your favorite IDE to find out how to make the IDE refresh the GuestList.txt file’s display.

ontheweb_fmt.eps In Listing 11-4, the condition roomNum < 10 && guests[roomNum] != 0 can be really tricky. If you move things around and write guests[roomNum] != 0 && roomNum < 10, you can get yourself into lots of trouble. For details, see this book’s website (www.allmycode.com/JavaForDummies).

Writing to a file

The code in Listing 11-4 uses tricks from other chapters and sections of this book. The code’s only brand-new feature is the use of PrintStream to write to a disk file. Think about any example in this book that calls System.out.print, out.println, or their variants. What’s really going on when you call one of these methods?

The thing called System.out is an object. The object is defined in the Java API. In fact, System.out is an instance of a class named java.io.PrintStream (or just PrintStream to its close friends). Now each object created from the PrintStream class has methods named print and println. Just as each Account object in Listing 7-3 has a display method, and just as the DecimalFormat object in Listing 10-1 has a format method, so the PrintStream object named out has print and println methods. When you call System.out.println, you’re calling a method that belongs to a PrintStream instance.

Okay, so what of it? Well, System.out always stands for some text area on your computer screen. If you create your own PrintStream object and you make that object refer to a disk file, that PrintStream object refers to the disk file. When you call that object’s print method, you write text to a file on your hard drive.

So in Listing 11-4, when you say

  PrintStream listOut =
            new PrintStream("GuestList.txt");
listOut.print(guests[roomNum]);    
listOut.print(" ");

you’re telling Java to write text to a file on your hard drive — the GuestList.txt file.

That’s how you update the count of guests staying in the hotel. When you call listOut.print for the number of guests in Room 3, you may print the number 5. So, between Figures 11-5 and 11-6, a number in the GuestList.txt file changes from 0 to 5. Then in Figure 11-6, you run the program a second time. When the program gets data from the newly written GuestList.txt file, Room 3 is no longer vacant. So this time, the program suggests Room 8.

tip.eps This is more an observation than a tip. Say that you want to read data from a file named Employees.txt. To do this, you make a scanner. You call new Scanner(new File("Employees.txt")). If you accidentally call new Scanner("Employees.txt") without the new File part, the call doesn’t connect to your Employees.txt file. But notice how you prepare to write data to a file. You make a PrintStream instance by calling new PrintStream("GuestList.txt"). You don’t use new File anywhere in the call. If you goof and accidentally include new File, the Java compiler becomes angry, jumps out, and bites you.

When to close a file

Notice the placement of new Scanner calls, new PrintStream calls, and close calls in Listing 11-4. As in all the examples, each new Scanner call has a corresponding close call. And in Listing 11-4, the new PrintStream call has its own close call (the listOut.close() call). But in Listing 11-4, I’m careful to place these calls tightly around their corresponding nextInt and print calls. For example, I don’t set up diskScanner at the very start of the program, and I don't wait until the very end of the program to close diskScanner. Instead, I perform all my diskScanner tasks one after the other in quick succession:

  Scanner diskScanner =
   new Scanner(new File("GuestList.txt"));  //construct
for (roomNum = 0; roomNum < 10; roomNum++) {
   guests[roomNum] = diskScanner.nextInt(); //read
}
diskScanner.close();                    //close

I do the same kind of thing with the keyboard and listOut objects.

I do this quick dance with input and output because my program uses GuestList.txt twice — once for reading numbers and a second time for writing numbers. If I’m not careful, the two uses of GuestList.txt might conflict with one another. Consider the following program:

  // THIS IS BAD CODE
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Scanner;
public class BadCode {
   
   public static void main(String args[])
                          throws IOException {
      int guests[] = new int[10];
      
      Scanner diskScanner =
         new Scanner(new File("GuestList.txt"));
      PrintStream listOut =
         new PrintStream("GuestList.txt");   
      
      guests[0] = diskScanner.nextInt();
      listOut.print(5);    
      
      diskScanner.close();
      listOut.close();
   }
}

Like many methods and constructors of its kind, the PrintStream constructor doesn’t pussyfoot around with files. If it can’t find a GuestList.txt file, the constructor creates a GuestList.txt file and prepares to write values into it. But, if a GuestList.txt file already exists, the PrintStream constructor deletes the existing file and prepares to write to a new, empty GuestList.txt file. So, in the BadCode class, the new PrintStream constructor call deletes whatever GuestList.txt file already exists. This deletion comes before the call to diskScanner.nextInt(). So diskScanner.nextInt() can't read whatever was originally in the GuestList.txt file. That's bad!

To avoid this disaster, I carefully separate the two uses of the GuestList.txt file in Listing 11-4. Near the top of the listing, I construct diskScanner, then read from the original GuestList.txt file, and then close diskScanner. Later, toward the end of the listing, I construct listOut, then write to a new GuestList.txt file, and then close listOut. With writing separated completely from reading, everything works correctly.

technicalstuff.eps The keyboard variable in Listing 11-4 doesn’t refer to GuestList.txt, so keyboard doesn't conflict with the other input or output variables. No harm would come from following my regular routine — putting keyboard = new Scanner(System.in) at the start of the program and putting keyboard.close() at the end of the program. But to make Listing 11-4 as readable and as uniform as possible, I place the keyboard constructor and the close call very tightly around the keyboard.nextInt call.

Arrays of Objects

The Java Motel is open for business, now with improved guest registration software! The people who brought you this chapter’s first section are always scratching their heads, looking for the best ways to improve their services. Now, with some ideas from object-oriented programming, they’ve started thinking in terms of a Room class.

“And what,” you ask, “would a Room instance look like?” That’s easy. A Room instance has three properties — the number of guests in the room, the room rate, and a smoking/nonsmoking stamp. Figure 11-8 illustrates the situation.

9781118407806-fg1108.tif

Figure 11-8: Another abstract snapshot of rooms in the Java Motel.

Listing 11-5 shows the code that describes the Room class. As promised, each instance of the Room class has three fields: the guests, rate, and smoking fields. (A false value for the boolean field, smoking, indicates a nonsmoking room.) In addition, the entire Room class has a static field named currency. This currency object makes room rates look like dollar amounts.

cross-reference.eps To find out what static means, see Chapter 10.

Listing 11-5: So This Is What a Room Looks Like!

  import static java.lang.System.out;
import java.util.Scanner;
import java.text.NumberFormat;
public class Room {
   private int guests;
   private double rate;
   private boolean smoking;
   private static NumberFormat currency =
      NumberFormat.getCurrencyInstance();
   public void readRoom(Scanner diskScanner) {
      guests = diskScanner.nextInt();
      rate = diskScanner.nextDouble();
      smoking = diskScanner.nextBoolean();
   }
   public void writeRoom() {
      out.print(guests);
      out.print(" ");
      out.print(currency.format(rate));
      out.print(" ");
      out.println(smoking ? "yes" : "no");
   }
}

Listing 11-5 has a few interesting quirks, but I’d rather not describe them until after you see all the code in action. That’s why, at this point, I move right on to the code that calls the Listing 11-5 code. After you read about arrays of rooms (shown in Listing 11-6), check out my description of the Listing 11-5 quirks.

warning.eps This warning is a deliberate repeat of an idea from Chapter 4, Chapter 7, and from who-knows-what-other chapter: You should be very careful when you use type double or type float to store money values. Calculations with double or float can be inaccurate. For more information (and more finger wagging) see Chapters 4 and 7.

tip.eps This tip has absolutely nothing to do with Java. If you're the kind of person who prefers a smoking room (with boolean field smoking = true in Listing 11-5), find someone you like — someone who can take three consecutive days off work. Have that person sit with you and comfort you for 72 straight hours while you refrain from smoking. You might become temporarily insane while the nicotine leaves your body, but eventually you'll be okay. And your friend will feel like a real hero.

Using the Room class

So now you need an array of rooms. The code to create such a thing is in Listing 11-6. The code reads data from the RoomList.txt file. (Figure 11-9 shows the contents of the RoomList.txt file.)

Figure 11-10 shows a run of the code in Listing 11-6.

Listing 11-6: Would You Like to See a Room?

  import static java.lang.System.out;
import java.util.Scanner;
import java.io.File;
import java.io.IOException;

public class ShowRooms {

   public static void main(String args[])
                          throws IOException {
      Room rooms[];
      rooms = new Room[10];
      
      Scanner diskScanner =
         new Scanner(new File("RoomList.txt"));
      for (int roomNum = 0; roomNum < 10; roomNum++) {
         rooms[roomNum] = new Room();
         rooms[roomNum].readRoom(diskScanner);
      }
      out.println("Room Guests Rate Smoking?");
      for (int roomNum = 0; roomNum < 10; roomNum++) {
         out.print(roomNum);
         out.print(" ");
         rooms[roomNum].writeRoom();
      }
      diskScanner.close();
   }
}

Say what you want about the code in Listing 11-6. As far as I’m concerned, only one issue in the whole listing should concern you. And what, you ask, is that issue? Well, to create an array of objects — as opposed to an array made up of primitive values — you have to do three things: make the array variable, make the array itself, and then construct each individual object in the array. This is different from creating an array of int values or an array containing any other primitive type values. When you create an array of primitive type values, you do only the first two of these three things.

To help make sense of all this, follow along in Listing 11-6 and Figure 11-11 as you read the following points:

  • Room rooms[];: This declaration creates a rooms variable. This variable is destined to refer to an array (but doesn’t yet refer to anything at all).
    9781118407806-fg1109.tif

    Figure 11-9: A file of Room data.

    9781118407806-fg1110.tif

    Figure 11-10: A run of the code in Listing 11-6.

  • rooms = new Room[10];: This statement reserves ten slots of storage in the computer’s memory. The statement also makes the rooms variable refer to the group of storage slots. Each slot is destined to refer to an object (but doesn’t yet refer to anything at all).
  • rooms[roomNum] = new Room();: This statement is inside a for loop. The statement is executed once for each of the ten room numbers. For example, the first time through the loop, this statement says rooms[0] = new Room(). That first time around, the statement makes the slot rooms[0] refer to an actual object (an instance of the Room class).
9781118407806-fg1111.tif

Figure 11-11: Steps in creating an array of objects.

Although it’s technically not considered a step in array making, you still have to fill each object’s fields with values. For instance, the first time through the loop, the readRoom call says rooms[1].readRoom(diskScanner), which means, “Read data from the RoomList.txt file into the rooms[1] object’s fields (the guests, rate, and smoking fields).” Each time through the loop, the program creates a new object and reads data into that new object’s fields.

You can squeeze the steps together just as you do when creating arrays of primitive values. For instance, you can do the first two steps in one fell swoop, like this:

  Room rooms[] = new Room[10];

You can also use an array initializer. (For an introduction to array initializers, see the section “Using an array initializer,” earlier in this chapter.)

Yet another way to beautify your numbers

You can make numbers look nice in plenty of ways. If you take a peek at some earlier chapters, for example, you can see that Listing 7-7 uses printf, and Listing 10-1 uses a DecimalFormat. But in Listing 11-5, I display a currency amount. I use the NumberFormat class with its getCurrencyInstance method.

If you compare the formatting statements in Listings 10-1 and 11-5, you don’t see much difference.

  • One listing uses a constructor; the other listing calls getCurrencyInstance. The getCurrencyInstance method is a good example of what’s called a factory method. A factory method is a convenient tool for creating commonly used objects. People always need code that displays dollar amounts. So the getCurrencyInstance method creates a dollar format without forcing you to write new DecimalFormat ("$###0.00;($###0.00)").

    Like a constructor, a factory method returns a brand-new object. But unlike a constructor, a factory method has no special status. When you create a factory method, you can name it anything you want. When you call a factory method, you don’t use the keyword new.

  • One listing uses DecimalFormat; the other listing uses NumberFormat. A decimal number is a certain kind of number. (In fact, a decimal number is a number written in the base-10 system.) Accordingly, the DecimalFormat class is a subclass of the NumberFormat class. The DecimalFormat methods are more specific, so for most purposes, I use DecimalFormat. But it’s harder to use the DecimalFormat class’s getCurrencyInstance method. So for programs that involve money, I tend to use NumberFormat.
  • Both listings use format methods. In the end, you just write something like currency.format(rate) or decFormat.format(average). After that, Java does the work for you.

remember.eps From Chapter 4 onward, I issue gentle warnings against using types such as double and float for storing currency values. For the most accurate currency calculations, use int, long, or best of all, BigDecimal.

You can read more about the dangers of double types, float types, and currency values in Chapter 5.

The conditional operator

Listing 11-5 uses an interesting doodad called the conditional operator. This conditional operator takes three expressions and returns the value of just one of them. It’s like a mini if statement. When you use the conditional operator, it looks something like this:

  conditionToBeTested ? expression1 : expression2

The computer evaluates the conditionToBeTested condition. If the condition is true, the computer returns the value of expression1. But, if the condition is false, the computer returns the value of expression2.

So, in the code

  smoking ? "yes" : "no"

the computer checks whether smoking has the value true. If so, the whole three-part expression stands for the first string, "yes". If not, the whole expression stands for the second string, "no".

In Listing 11-5, the call to out.println causes either "yes" or "no" to display. Which string gets displayed depends on whether smoking has the value true or false.

Command Line Arguments

Once upon a time, most programmers used a text-based development interface. To run the Displayer example in Chapter 3, they didn't select Run from a menu in a fancy integrated development environment. Instead they typed a command in a plain-looking window, usually with white text on a black background. Figure 11-12 illustrates the point. In Figure 11-12, I type the words java Displayer, and the computer responds with my Java program's output (the words You'll love Java!).

9781118407806-fg1112.tif

Figure 11-12: How dull!

The plain-looking window goes by the various names, depending on the kind of operating system that you use. In Windows, a text window of this kind is a command prompt window. On a Macintosh and in Linux, this window is the terminal. Some versions of Linux and UNIX call this window a shell.

Anyway, back in ancient times, you could write a program that sucked up extra information when you typed the command to launch the program. Figure 11-13 shows you how this worked.

9781118407806-fg1113.tif

Figure 11-13: When you launch MakeRandomNumsFile, you type some extra information.

In Figure 11-13, the programmer types java MakeRandomNumsFile to run the MakeRandomNumsFile program. But the programmer follows java MakeRandomNumsFile with two extra pieces of information; namely, MyNumberedFile.txt and 5. When the MakeRandomNumsFile program runs, the program sucks up two extra pieces of information and uses them to do whatever the program has to do. In Figure 11-13, the program sucks up MyNumberedFile.txt 5, but on another occasion the programmer might type SomeStuff 28 or BunchONumbers 2000. The extra information can be different each time you run the program.

So the next question is, “How does a Java program know that it’s supposed to snarf up extra information each time it runs?” Since you first started working with Java, you’ve been seeing this String args[] business in the header of every main method. Well, it’s high time you found out what that’s all about. The parameter args[] is an array of String values. These String values are called command line arguments.

Using command line arguments in a Java program

Listing 11-7 shows you how to use command line arguments in your code.

Listing 11-7: Generate a File of Numbers

  import java.util.Random;
import java.io.PrintStream;
import java.io.IOException;
public class MakeRandomNumsFile {
   
  public static void main(String args[])
                           throws IOException {
     Random generator = new Random();
    
     if (args.length < 2) {
       System.out.println
        ("Usage: MakeRandomNumsFile filename number");
       System.exit(1);
     }
    
     PrintStream printOut = new PrintStream(args[0]);
     int numLines = Integer.parseInt(args[1]);
    
     for (int count = 1; count <= numLines; count++) {
       printOut.println(generator.nextInt(10) + 1);
     }
     printOut.close();
  }
}

ontheweb_fmt.eps If a particular program expects some command line arguments, you can’t start the program running the same way you’d start most of the other programs in this book. The way you feed command line arguments to a program depends on the IDE that you’re using — Eclipse, NetBeans, or whatever. That's why this book’s website (www.allmycode.com/JavaForDummies) has instructions for feeding arguments to programs using various IDEs.

When the code in Listing 11-7 begins running, the args array gets its values. In the main method of Listing 11-7, the array component args[0] automatically takes on the value "MyNumberedFile.txt", and args[1] automatically becomes "5". So the program’s assignment statements end up having the following meaning:

  PrintStream printOut = new 
PrintStream("MyNumberedFile.txt");
int numLines = Integer.parseInt("5");

The program creates a file named MyNumberedFile.txt and sets numLines to 5. So later in the code, the program randomly generates five values and puts those values into MyNumberedFile.txt. One run of the program gives me the file shown in Figure 11-14.

9781118407806-fg1114.tif

Figure 11-14: A file from a run of the code in Listing 11-7.

tip.eps After running the code in Listing 11-7, where can you find the new file (My
NumberedFile.txt) on your hard drive? The answer depends on a lot of different things, so I don’t want to commit to one particular answer. If you use an IDE with programs divided into projects, then the new file is somewhere in the project’s folder. One way or another, you can change Listing 11-7 to specify a full path name — a name like "c:\MyNumberedFile.txt".

remember.eps In Windows, file path names contain backslash characters. And in Java, when you want to indicate a backslash inside a double-quoted String literal, you use a double backslash instead. That’s why "c:\MyNumberedFile.txt" contains two backslashes. In contrast, file paths in the Linux and Macintosh operating systems contain forward slashes. To indicate a forward slash in a Java String, use one forward slash. To refer to a file in your Macintosh Documents directory, you might write "/Users/YourUserName/Documents/MyNumberedFile.txt".

Notice how each command line argument in Listing 11-7 is a String value. When you look at args[1], you don’t see the number 5 — you see the string "5" with a digit character in it. Unfortunately, you can’t use that "5" to do any counting. To get an int value from "5", you have to apply the parseInt method. (Again, see Listing 11-7.)

The parseInt method lives inside a class named Integer. So, to call parseInt, you preface the name parseInt with the word Integer. The Integer class has all kinds of handy methods for doing things with int values.

remember.eps In Java, Integer is the name of a class, and int is the name of a primitive (simple) type. The two things are related, but they’re not the same. The Integer class has methods and other tools for dealing with int values.

Checking for the right number of command line arguments

What happens if the user makes a mistake? What if the user forgets to type the number 5 on the first line in Figure 11-13?

Then the computer assigns "MyNumberedFile.txt" to args[0], but it doesn’t assign anything to args[1]. This is bad. If the computer ever reaches the statement

  int numLines = Integer.parseInt(args[1]);

the program crashes with an unfriendly ArrayIndexOutOfBoundsException.

So, what do you do about this? In Listing 11-7, you check the length of the args array. You compare args.length with 2. If the args array has fewer than two components, you display a message on the screen and exit from the program. Figure 11-15 shows the resulting output.

9781118407806-fg1115.tif

Figure 11-15: The code in Listing 11-7 tells you how to run it.

warning.eps Despite the checking of args.length in Listing 11-7, the code still isn’t crash-proof. If the user types five instead of 5, the program takes a nosedive with a NumberFormatException. The second command line argument can’t be a word. The argument has to be a number (and a whole number at that). I can add statements to Listing 11-7 to make the code more bulletproof, but checking for the NumberFormatException is better done in Chapter 13.

When you’re working with command line arguments, you can enter a String value with a blank space in it. Just enclose the value in double quote marks. For instance, you can run the code of Listing 11-7 with arguments "My Big Fat File.txt" 7.

ontheweb_fmt.eps The sun is about to set on this book’s discussion of arrays. The next section deals with something slightly different. But before you leave the subject of arrays, think about this: An array is a row of things, and not every kind of thing fits into just one row. Take the first few examples in this chapter involving the motel. The motel rooms, numbered 0 through 9, are in one big line. But what if you move up in the world? You buy a big hotel with 50 floors and with 100 rooms on each floor. Then the data is square shaped. We have 50 rows, and each row contains 100 items. Sure, you can think of the rooms as if they’re all in one big row, but why should you have to do that? How about having a two-dimensional array? It’s a square-shaped array in which each component has two indices — a row number and a column number. Alas, I have no space in this book to show you a two-dimensional array (and I can’t afford a big hotel’s prices anyway). But if you visit this book’s website (www.allmycode.com/JavaForDummies), you can read all about it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.140.195.225