BUY THIS BOOK
Add to Cart

Print Book $39.95


Add to Cart

Print+PDF $51.94

Add to Cart

PDF $39.95

Safari Books Online

What is this?

Add to UK Cart

Print Book £28.50

What is this?

Looking to Reprint or License this content?


Java Examples in a Nutshell
Java Examples in a Nutshell, Third Edition

By David Flanagan
Book Price: $39.95 USD
£28.50 GBP
PDF Price: $39.95

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Java Basics
This chapter contains examples that demonstrate the basic syntax of Java; it is meant to be used in conjunction with Chapter 2 of Java in a Nutshell. If you have substantial programming experience with C or C++, you should find the material in this chapter straightforward. If you are coming to Java from another language, however, you may need to study the examples here more carefully.
The most important step in learning a new programming language is mastering the basic control statements of the language. With Java, this means learning the if/else branching statement and the while and for looping statements. Learning to program well is like learning to do word problems in high-school algebra class: you have to translate the problem from an abstract description into the concrete language of algebra (or, in this case, the language of Java). Once you learn to think in if, while, and for statements, other Java statements, such as break, continue, switch, and try/catch/finally, should be easy to pick up. Note that although Java is an object-oriented language, we won't discuss objects until Chapter 2.
So, with that as an introduction, and with mastery of basic syntax as our goal, let's jump right in and start writing Java programs.
As long ago as 1978, Brian Kernighan and Dennis Ritchie wrote, in their classic book The C Programming Language, that "the first program to write is the same for all languages." They were referring, of course, to the "Hello World" program. The Java implementation of Hello World is shown in Example 1-1.
Example 1-1. Hello.java
package je3.basics;                          // A unique class name prefix
public class Hello {                         // Everything in Java is a class
    public static void main(String[  ] args) { // All programs must have main( )
        System.out.println("Hello World!");  // Say hello!
    }                                        // This marks the end of main( )
}                                            // Marks the end of the class
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Hello World
As long ago as 1978, Brian Kernighan and Dennis Ritchie wrote, in their classic book The C Programming Language, that "the first program to write is the same for all languages." They were referring, of course, to the "Hello World" program. The Java implementation of Hello World is shown in Example 1-1.
Example 1-1. Hello.java
package je3.basics;                          // A unique class name prefix
public class Hello {                         // Everything in Java is a class
    public static void main(String[  ] args) { // All programs must have main( )
        System.out.println("Hello World!");  // Say hello!
    }                                        // This marks the end of main( )
}                                            // Marks the end of the class
The first line of this program is the package declaration. It specifies the name of the package of which this program is part. The program's name (as we'll see in the second line) is Hello. The package name is je3.basics. We can combine these two names to produce a fully qualified name, je3.basics.Hello. Using packages provides a unique namespace for every Java program. By placing this Hello program in a package, I've helped to ensure that no naming conflict will arise if someone else defines a program that is also named Hello. Each chapter of this book has its own package that begins with the prefix je3 (for JavaExamples3). In this case, since this is the basics chapter, the package name is je3.basics.
The value of "Hello World" is that it is a template that you can expand on in your later experiments with Java. The second and third lines of Example 1-1 are a required part of the template. Every program—every piece of Java code, really—you write is a class. The second line of the example says that we're writing a class named Hello. It also says the class is public, which means it can be used by anyone.
Every standalone Java program requires a
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
FizzBuzz
FizzBuzz is a game I learned long ago in elementary-school French class, as a way to practice counting in that language. The players take turns counting, starting with one and going up. The rules are simple: when your turn arrives, you say the next number. However, if that number is a multiple of five, you should say the word "fizz" (preferably with a French accent) instead. If the number is a multiple of seven, you should say "buzz." And if it is a multiple of both, you should say "fizzbuzz." If you mess up, you're out, and the game continues without you.
Example 1-2 is a Java program named FizzBuzz that plays a version of the game. Actually, it isn't a very interesting version of the game because the computer plays by itself, and it doesn't count in French! What is interesting to us is the Java code that goes into this example. It demonstrates the use of a for loop to count from 1 to 100 and the use of if/else statements to decide whether to output the number or one of the words "fizz", "buzz", or "fizzbuzz". (In this case, the if/else statement is used as an if/elseif/elseif/else statement, as we'll discuss shortly.)
This program introduces System.out.print( ). This method is just like System.out.println( ), except that it doesn't terminate the line of output. Whatever is output next appears on the same line.
The example also shows another style for comments. Anything, on any number of lines, between the characters /* and the characters */ is a comment in Java and ignored by the compiler. When one of these comments begins with /**, as the one in this example does, then it is additionally a doc comment, which means its contents are used by the javadoc program that automatically generates API documentation from Java source code.
Example 1-2. FizzBuzz.java
package je3.basics;

/**
 * This program plays the game "Fizzbuzz".  It counts to 100, replacing each
 * multiple of 5 with the word "fizz", each multiple of 7 with the word "buzz",
 * and each multiple of both with the word "fizzbuzz".  It uses the modulo
 * operator (%) to determine if a number is divisible by another.
 **/
public class FizzBuzz {                      // Everything in Java is a class
    public static void main(String[  ] args) { // Every program must have main( )
        for(int i = 1; i <= 100; i++) {           // count from 1 to 100
            if (((i % 5) == 0) && ((i % 7) == 0)) // Is it a multiple of 5 & 7?
                System.out.print("fizzbuzz");   
            else if ((i % 5) == 0)                // Is it a multiple of 5?
                System.out.print("fizz"); 
            else if ((i % 7) == 0)                // Is it a multiple of 7?
                System.out.print("buzz"); 
            else System.out.print(i);             // Not a multiple of 5 or 7
            System.out.print(" ");                
        }
        System.out.println( );
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Fibonacci Series
The Fibonacci numbers are a sequence of numbers in which each successive number is the sum of the two preceding numbers. The sequence begins 1, 1, 2, 3, 5, 8, 13, and goes on from there. This sequence appears in interesting places in nature. For example, the number of petals on most species of flowers is one of the Fibonacci numbers.
Example 1-3 shows a program that computes and displays the first 20 Fibonacci numbers. There are several things to note about the program. First, it again uses a for statement. It also declares and uses variables to hold the previous two numbers in the sequence, so that these numbers can be added together to produce the next number in the sequence.
Example 1-3. Fibonacci.java
package je3.basics;
/**
 * This program prints out the first 20 numbers in the Fibonacci sequence.
 * Each term is formed by adding together the previous two terms in the
 * sequence, starting with the terms 1 and 1.
 **/
public class Fibonacci {
    public static void main(String[  ] args) {
        int n0 = 1, n1 = 1, n2;          // Initialize variables
        System.out.print(n0 + " " +      // Print first and second terms
                         n1 + " ");      // of the series

        for(int i = 0; i < 18; i++) {    // Loop for the next 18 terms
            n2 = n1 + n0;                // Next term is sum of previous two
            System.out.print(n2 + " ");  // Print it out
            n0 = n1;                     // First previous becomes 2nd previous
            n1 = n2;                     // And current number becomes previous
        }
        System.out.println( );            // Terminate the line
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using Command-Line Arguments
As we've seen, every standalone Java program must declare a method with exactly the following signature:
public static void main(String[  ] args)
This signature says that an array of strings is passed to the main( ) method. What are these strings, and where do they come from? The args array contains any arguments passed to the Java interpreter on the command line, following the name of the class to be run. Example 1-4 shows a program, Echo, that reads these arguments and prints them back out. For example, you can invoke the program this way:
% java je3.basics.Echo this is a test
The program responds:
this is a test
In this case, the args array has a length of four. The first element in the array, args[0], is the string "this", and the last element of the array, args[3], is "test". As you can see, Java arrays begin with element 0. If you are coming from a language that uses one-based arrays, this can take quite a bit of getting used to. In particular, you must remember that if the length of an array a is n, the last element in the array is a[n-1]. You can determine the length of an array by appending .length to its name, as shown in Example 1-4.
This example also demonstrates the use of a while loop. A while loop is a simpler form of the for loop; it requires you to do your own initialization and update of the loop counter variable. Most for loops can be rewritten as a while loop, but the compact syntax of the for loop makes it the more commonly used statement. A for loop would have been perfectly acceptable, and even preferable, in this example.
Example 1-4. Echo.java
package je3.basics;

/**
 * This program prints out all its command-line arguments.
 **/
public class Echo {
    public static void main(String[  ] args) {
        int i = 0;                           // Initialize the loop variable
        while(i < args.length) {             // Loop until the end of array
            System.out.print(args[i] + " "); // Print each argument out
            i++;                             // Increment the loop variable
        }
        System.out.println( );                // Terminate the line
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Echo in Reverse
Example 1-5 is a lot like the Echo program of Example 1-4, except that it prints out the command-line arguments in reverse order, and it prints out the characters of each argument backwards. Thus, the Reverse program can be invoked as follows, with the following output:
% java je3.basics.Reverse this is a test
tset a si siht
This program is interesting because its nested for loops count backward instead of forward. It is also interesting because it manipulates String objects by invoking methods of those objects and the syntax starts to get a little complicated. For example, consider the expression at the heart of this example:
args[i].charAt(j)
This expression first extracts the ith element of the args[ ] array. We know from the declaration of the array in the signature of the main( ) method that it is a String array; that is, it contains String objects. (Strings are not a primitive type, like integers and boolean values in Java: they are full-fledged objects.) Once you extract the ith String from the array, you invoke the charAt( ) method of that object, passing the argument j. (The . character in the expression refers to a method or a field of an object.) As you can surmise from the name (and verify, if you want, in a reference manual), this method extracts the specified character from the String object. Thus, this expression extracts the jth character from the ith command-line argument. Armed with this understanding, you should be able to make sense of the rest of Example 1-5.
Example 1-5. Reverse.java
package je3.basics;

/**
 * This program echos the command-line arguments backwards.
 **/
public class Reverse {
    public static void main(String[  ] args) {
        // Loop backwards through the array of arguments
        for(int i = args.length-1; i >= 0; i--) {
            // Loop backwards through the characters in each argument
            for(int j=args[i].length( )-1; j>=0; j--) {
                // Print out character j of argument i.
                System.out.print(args[i].charAt(j));
            }
            System.out.print(" ");  // Add a space at the end of each argument.
        }
        System.out.println( );       // And terminate the line when we're done.
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
FizzBuzz Switched
Example 1-6 is another version of the FizzBuzz game. This version uses a switch statement instead of nested if/else statements to determine what its output should be for each number. Take a look at the example first, then read the explanation of switch.
Example 1-6. FizzBuzz2.java
package je3.basics;

/**
 * This class is much like the FizzBuzz class, but uses a switch statement
 * instead of repeated if/else statements
 **/
public class FizzBuzz2 {
    public static void main(String[  ] args) {
        for(int i = 1; i <= 100; i++) { // count from 1 to 100
            switch(i % 35) {      // What's the remainder when divided by 35?
            case 0:                      // For multiples of 35...
                System.out.print("fizzbuzz ");  // print "fizzbuzz".
                break;                          // Don't forget this statement!
            case 5: case 10: case 15:    // If the remainder is any of these
            case 20: case 25: case 30:   // then the number is a multiple of 5
                System.out.print("fizz ");      // so print "fizz".
                break;
            case 7: case 14: case 21: case 28:  // For any multiple of 7...
                System.out.print("buzz ");      // print "buzz".
                break;
            default:                            // For any other number...
                System.out.print(i + " ");      // print the number.
                break;
            }
        }
        System.out.println( );
    }
}
The switch statement acts like a switch operator at a busy rail yard, switching a train (or the execution of a program) to the appropriate track (or piece of code) out of many potential tracks. A switch statement is often an alternative to repeated if/else statements, but it only works when the value being tested is an integer (i.e., long, float, double, boolean, and reference types such as String objects are not allowed) and when the value is being tested against constant values. The basic syntax of the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Computing Factorials
The factorial of an integer is the product of that number and all of the positive integers smaller than it. Thus the factorial of 5, written 5!, is the product of 5*4*3*2*1, or 120. Example 1-7 shows a class, Factorial, that contains a method, factorial( ), that computes factorials. This class is not a program in its own right, but the method it defines can be used by other programs. The method itself is quite simple; we'll see several variations of it in the following sections. As an exercise, you might think about how you could rewrite this example using a while loop instead of a for loop.
Example 1-7. Factorial.java
package je3.basics;
/**
 * This class doesn't define a main( ) method, so it isn't a program by itself.
 * It does define a useful method that we can use in other programs, though.
 **/
public class Factorial {
    /** Compute and return x!, the factorial of x */
    public static int factorial(int x) {
        if (x < 0) throw new IllegalArgumentException("x must be >= 0");
        int fact = 1;
        for(int i = 2; i <= x; i++)    // loop
            fact *= i;                 // shorthand for: fact = fact * i;
        return fact;
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Recursive Factorials
Example 1-8 shows another way to compute factorials. This example uses a programming technique called recursion. Recursion happens when a method calls itself, or in other words, invokes itself recursively. The recursive algorithm for computing factorials relies on the fact that n! is equal to n*(n-1)!. Computing factorials in this fashion is a classic example of recursion. It is not a particularly efficient technique in this case, but there are many important uses for recursion, and this example demonstrates that it is perfectly legal in Java. This example also switches from the int data type, which is a 32-bit integer, to the long data type, which is a 64-bit integer. Factorials become very large, very quickly, so the extra capacity of a long makes the factorial( ) method more useful.
Example 1-8. Factorial2.java
package je3.basics;
/**
 * This class shows a recursive method to compute factorials.  This method
 * calls itself repeatedly based on the formula: n! = n * (n-1)!
 **/
public class Factorial2 {
    public static long factorial(long x) {
        if (x < 0) throw new IllegalArgumentException("x must be >= 0");
        if (x <= 1) return 1;              // Stop recursing here
        else return x * factorial(x-1);    // Recurse by calling ourselves
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Caching Factorials
Example 1-9 shows a refinement to our previous factorial examples. Factorials are ideal candidates for caching because they are slightly time consuming to compute, and more importantly, there are few factorials you actually can compute, due to the limitations of the long data type. So, in this example, once a factorial is computed, its value is stored for future use.
Besides introducing the technique of caching, this example demonstrates several new things. First, it declares static fields within the Factorial3 class:
static long[  ] table = new long[21];
static int last = 0;
A static field is kind of like a variable, but it retains its value between invocations of the factorial( ) method. This means that static fields can cache values computed in one invocation for use by the next invocation.
Second, this example shows how to create an array:
static long[  ] table = new long[21];
The first half of this line (before the = sign) declares the static field table to be an array of long values. The second half of the line actually creates an array of 21 long values using the new operator.
Finally, this example demonstrates how to throw an exception:
throw new IllegalArgumentException("Overflow; x is too large.");
An exception is a kind of Java object; it is created with the new keyword, just as the array was. When a program throws an exception object with the throw statement, it indicates that some sort of unexpected circumstance or error has arisen. When an exception is thrown, program control transfers to the nearest containing catch clause of a try/catch statement. This clause should contain code to handle the exceptional condition. If an exception is never caught, the program terminates with an error.
Example 1-9 throws an exception to notify the calling procedure that the argument it passed is too big or too small. The argument is too big if it is greater than 20, since we can't compute factorials beyond
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Computing Big Factorials
In the previous section, we learned that 20! is the largest factorial that can fit in a 64-bit integer. But what if you want to compute 50! or 100!? The java.math.BigInteger class represents arbitrarily large integer values and provides methods to perform arithmetic operations on these very large numbers. Example 1-10 uses the BigInteger class to compute factorials of any size. It also includes a simple main( ) method that defines a standalone test program for our factorial( ) method. This test program says, for example, that 50! is the following 65-digit number:
30414093201713378043612608166064768844377641568960512000000000000
Example 1-10 introduces the import statement. This statement must appear at the top of a Java file, before any class is defined (but after the package declaration). It provides a way to tell the compiler what classes you are using in a program. Once a class like java.math.BigInteger has been imported, you no longer have to type its full name; instead you can refer to it simply as BigInteger. You can also import an entire package of classes, as with the line:
import java.util.*
Note that the classes in the java.lang package are automatically imported, as are the classes of the current package, which, in this case, is je3.basics.
Example 1-10 uses the same caching technique Example 1-9 did. However, because there is no upper bound on the number of factorials that can be computed with this class, you can't use a fixed-sized array for the cache. Instead, use the java.util.ArrayList class, which is a utility class that implements an array-like data structure that can grow to be as large as you need it to be. Because an ArrayList is an object rather than an array, you use such methods as size( ), add( ), and get( ) to work with it. By the same token, a BigInteger is an object rather than a primitive value, so you can't simply use the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Handling Exceptions
Example 1-11 shows a program that uses the Integer.parseInt( ) method to convert a string specified on the command line to a number. The program then computes and prints the factorial of that number, using the Factorial4.factorial( ) method defined in Example 1-10. That much is simple; it takes only two lines of code. The rest of the example is concerned with exception handling, or, in other words, taking care of all of the things that can go wrong. You use the try/catch statement in Java for exception handling. The try clause encloses a block of code from which exceptions may be thrown. It is followed by any number of catch clauses; the code in each catch clause takes care of a particular type of exception.
In Example 1-11, there are three possible user-input errors that can prevent the program from executing normally. Therefore, the two main lines of program code are wrapped in a try clause followed by three catch clauses. Each clause notifies the user about a particular error by printing an appropriate message. This example is fairly straightforward. You may want to consult Chapter 2 of Java in a Nutshell, as it explains exceptions in more detail.
Example 1-11. FactComputer.java
package je3.basics;

/**
 * This program computes and displays the factorial of a number specified
 * on the command line.  It handles possible user input errors with try/catch.
 **/
public class FactComputer {
    public static void main(String[  ] args) {
        // Try to compute a factorial.
        // If something goes wrong, handle it in the catch clause below.
        try {
            int x = Integer.parseInt(args[0]);
            System.out.println(x + "! = " + Factorial4.factorial(x));
        }
        // The user forgot to specify an argument.
        // Thrown if args[0] is undefined.
        catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("You must specify an argument");
            System.out.println("Usage: java FactComputer <number>");
        }
        // The argument is not a number.  Thrown by Integer.parseInt( ).
        catch (NumberFormatException e) {
            System.out.println("The argument you specify must be an integer");
        }
        // The argument is < 0.  Thrown by Factorial4.factorial( )
        catch (IllegalArgumentException e) {
            // Display the message sent by the factorial( ) method:
            System.out.println("Bad argument: " + e.getMessage( ));
        }
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Interactive Input
Example 1-12 shows yet another program for computing factorials. Unlike Example 1-11, however, it doesn't just compute one factorial and quit. Instead, it prompts the user to enter a number, reads that number, prints its factorial, and then loops and asks the user to enter another number. The most interesting thing about this example is the technique it uses to read user input from the keyboard. It uses the readLine( ) method of a BufferedReader object to do this. The line that creates the BufferedReader may look confusing. For now, take it on faith that it works; you don't really need to understand how it works until we reach Chapter 3. Another feature of note in Example 1-12 is the use of the equals( ) method of the String object line to check whether the user has typed "quit".
The code for parsing the user's input and computing and printing the factorial is the same as in Example 1-11, and again, it is enclosed within a try clause. In Example 1-12, however, there is only a single catch clause to handle the possible exceptions. This one handles any exception object of type Exception. Exception is the superclass of all exception types, so this one catch clause is invoked no matter what type of exception is thrown.
Example 1-12. FactQuoter.java
package je3.basics;
import java.io.*; // Import all classes in java.io package.  Saves typing.

/**
 * This program displays factorials as the user enters values interactively
 **/
public class FactQuoter {
    public static void main(String[  ] args) throws IOException {
        // This is how we set things up to read lines of text from the user.
        BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
        // Loop forever
        for(;;) {
            // Display a prompt to the user
            System.out.print("FactQuoter> ");
            // Read a line from the user
            String line = in.readLine( );
            // If we reach the end-of-file, 
            // or if the user types "quit", then quit
            if ((line == null) || line.equals("quit")) break;
            // Try to parse the line, and compute and print the factorial
            try { 
                int x = Integer.parseInt(line);
                System.out.println(x + "! = " + Factorial4.factorial(x)); 
            }
            // If anything goes wrong, display a generic error message
            catch(Exception e) { System.out.println("Invalid Input"); }
        }
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using a StringBuffer
One of the things you may have noticed about the String class that is used to represent strings in Java is that it is immutable. In other words, there are no methods that allow you to change the contents of a string. Methods that operate on a string return a new string, not a modified copy of the old one. When you want to operate on a string in place, you must use a StringBuffer object instead.
Example 1-13 demonstrates the use of a StringBuffer. It interactively reads a line of user input, as Example 1-12 did, and creates a StringBuffer to contain the line. The program then encodes each character of the line using the rot13 substitution cipher, which simply "rotates" each letter 13 places through the alphabet, wrapping around from Z back to A when necessary. Because a StringBuffer object is being used, you can replace each character in the line one-by-one. A session with this Rot13Input program might look like this:
% java je3.basics.Rot13Input
> Hello there.  Testing, testing!
Uryyb gurer.  Grfgvat, grfgvat!
> quit
%
The main( ) method of Example 1-13 calls another method, rot13( ), to perform the actual encoding of a character. This method demonstrates the use of the primitive Java char type and character literals (i.e., characters that are used literally in a program within single quotes).
Example 1-13. Rot13Input.java
package je3.basics;
import java.io.*;  // We're doing input, so import I/O classes

/**
 * This program reads lines of text from the user, encodes them using the 
 * trivial "Rot13" substitution cipher, and then prints out the encoded lines.
 **/
public class Rot13Input {
    public static void main(String[  ] args) throws IOException {
        // Get set up to read lines of text from the user
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        for(;;) {                                    // Loop forever
            System.out.print("> ");                    // Print a prompt
            String line = in.readLine( );               // Read a line
            if ((line == null) || line.equals("quit")) // If EOF or "quit"...
                break;                                 // ...break out of loop
            StringBuffer buf = new StringBuffer(line); // Use a StringBuffer
            for(int i = 0; i < buf.length( ); i++)      // For each character...
                buf.setCharAt(i, rot13(buf.charAt(i)));// ..read, encode, store
            System.out.println(buf);                   // Print encoded line
        }
    }
    
    /**
     * This method performs the Rot13 substitution cipher.  It "rotates"
     * each letter 13 places through the alphabet.  Since the Latin alphabet
     * has 26 letters, this method both encodes and decodes.
     **/
    public static char rot13(char c) {
        if ((c >= 'A') && (c <= 'Z')) {  // For uppercase letters
            c += 13;                       // Rotate forward 13
            if (c > 'Z') c -= 26;          // And subtract 26 if necessary
        }
        if ((c >= 'a') && (c <= 'z')) {  // Do the same for lowercase letters
            c += 13;
            if (c > 'z') c -= 26;
        }
        return c;                        // Return the modified letter
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Sorting Numbers
Example 1-14 implements a simple (but inefficient) algorithm for sorting an array of numbers. This example doesn't introduce any new elements of Java syntax, but it is interesting because it reaches a real-world level of complexity. The sorting algorithm manipulates array entries using an if statement within a for loop that is itself within another for loop. You should take the time to study this short program carefully. Make sure that you understand exactly how it goes about sorting its array of numbers.
Example 1-14. SortNumbers.java
package je3.basics;

/**
 * This class demonstrates how to sort numbers using a simple algorithm
 **/
public class SortNumbers {
    /**
     * This is a very simple sorting algorithm that is not very efficient
     * when sorting large numbers of things
     **/
    public static void sort(double[  ] nums) {
        // Loop through each element of the array, sorting as we go.
        // Each time through, find the smallest remaining element, and move it
        // to the first unsorted position in the array.
        for(int i = 0; i < nums.length; i++) {
            int min = i;  // holds the index of the smallest element
            // find the smallest one between i and the end of the array
            for(int j = i; j < nums.length; j++) {
                if (nums[j] < nums[min]) min = j;
            }
            // Now swap the smallest one with element i.  
            // This leaves all elements between 0 and i sorted.
            double tmp;
            tmp = nums[i];
            nums[i] = nums[min];
            nums[min] = tmp;
        }
    }

    /** This is a simple test program for the algorithm above */
    public static void main(String[  ] args) {
        double[  ] nums = new double[10];      // Create an array to hold numbers
        for(int i = 0; i < nums.length; i++) // Generate random numbers
            nums[i] = Math.random( ) * 100;
        sort(nums);                          // Sort them
        for(int i = 0; i < nums.length; i++) // Print them out
            System.out.println(nums[i]);
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Computing Primes
Example 1-15 computes the largest prime number less than a specified value, using the Sieve of Eratosthenes algorithm. The algorithm finds primes by eliminating multiples of all lower prime numbers. Like Example 1-14, this example introduces no new Java syntax, but is a nice, nontrivial program with which to end this chapter. The program may seem deceptively simple, but there's actually a fair bit going on, so be sure you understand how it is ruling out prime numbers.
Example 1-15. Sieve.java
package je3.basics;

/**
 * This program computes prime numbers using the Sieve of Eratosthenes
 * algorithm: rule out multiples of all lower prime numbers, and anything
 * remaining is a prime.  It prints out the largest prime number less than
 * or equal to the supplied command-line argument.
 **/
public class Sieve {
    public static void main(String[  ] args) {
        // We will compute all primes less than the value specified on the
        // command line, or, if no argument, all primes less than 100.
        int max = 100;                           // Assign a default value
        try { max = Integer.parseInt(args[0]); } // Parse user-supplied arg
        catch (Exception e) {  }                   // Silently ignore exceptions.

        // Create an array that specifies whether each number is prime or not.
        boolean[  ] isprime = new boolean[max+1];

        // Assume that all numbers are primes, until proven otherwise.
        for(int i = 0; i <= max; i++) isprime[i] = true;

        // However, we know that 0 and 1 are not primes.  Make a note of it.
        isprime[0] = isprime[1] = false;

        // To compute all primes less than max, we need to rule out
        // multiples of all integers less than the square root of max.
        int n = (int) Math.ceil(Math.sqrt(max));  // See java.lang.Math class

        // Now, for each integer i from 0 to n:
        //   If i is a prime, then none of its multiples are primes,
        //   so indicate this in the array.  If i is not a prime, then
        //   its multiples have already been ruled out by one of the
        //   prime factors of i, so we can skip this case.
        for(int i = 0; i <= n; i++) {
            if (isprime[i])                          // If i is a prime, 
                for(int j = 2*i; j <= max; j = j + i) // loop through multiples
                    isprime[j] = false;               // they are not prime.
        }

        // Now go look for the largest prime:
        int largest;
        for(largest = max; !isprime[largest]; largest--) ;  // empty loop body
        
        // Output the result
        System.out.println("The largest prime less than or equal to " + max +
                           " is " + largest);
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Exercises
  • Exercise 1-1. Write a program that counts from 1 to 15, printing out each number, and then counts backward by twos back to 1, again printing out each number.
  • Exercise 1-2. Each term of the Fibonacci series is formed by adding the previous two terms. What sort of series do you get if you add the previous three terms? Write a program to print the first 20 terms of this series.
  • Exercise 1-3. Write a program that takes two numbers and a string as command-line arguments and prints out the substring of the string specified by the two numbers. For example:
    % java Substring hello 1 3
    should print out:
    ell
    Handle all possible exceptions that might arise because of bad input.
  • Exercise 1-4. Write a program that interactively reads lines of input from the user and prints them back out, reversed. The program should exit if the user types "tiuq".
  • Exercise 1-5. The SortNumbers class shows how you can sort an array of doubles. Write a program that uses this class to sort an array of 100 floating-point numbers. Then, interactively prompt the user for numeric input, and display the next larger and next smaller number from the array. You should use an efficient binary search algorithm to find the desired position in the sorted array.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Objects, Classes, and Interfaces
This chapter contains examples that illustrate the object-oriented nature of Java and show you how to define and use classes and interfaces. It is designed to be read in conjunction with Chapter 3 of Java in a Nutshell, which offers a complete introduction to the object-oriented concepts and syntax you must understand to program in Java. As a refresher, the following paragraphs summarize Java's object-oriented terminology.
An object is a collection of data values, or fields, plus methods that operate on that data. The data type of an object is called a class; an object is often referred to as an instance of its class. The class defines the type of each field in an object, and it provides the methods that operate on data contained in an instance of the class. An object is created using the new operator, which invokes a constructor of the class to initialize the new object. The fields and methods of an object are accessed and invoked using the . operator.
Methods that operate on the fields of an object are known as instance methods. They are different from the static, or class, methods that we saw in Chapter 1. Class methods are declared static; they operate on the class itself, rather than on an individual instance of the class. Fields of a class may also be declared static, which makes them class fields instead of instance fields. While each object has its own copy of each instance field, there is only one copy of a class field and it is shared by all instances of the class.
The fields and methods of a class may have different visibility levels, including public, private, and protected. These different levels of visibility allow fields and methods to be used in different contexts. Every class has a superclass, from which it inherits fields and methods. When a class inherits from another class, it is called a subclass of that class. Classes in Java form a class hierarchy
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
A Rectangle Class
Example 2-1 shows a class that represents a rectangle. Each instance of this Rect class has four fields, x1, y1, x2, and y2, that define the coordinates of the corners of the rectangle. The Rect class also defines a number of methods that operate on those coordinates.
Note the toString( ) method. This method overrides the toString( ) method of java.lang.Object, which is the implicit superclass of the Rect class. toString( ) produces a String that represents a Rect object. As you'll see, this method is quite useful for printing out Rect values.
Example 2-1. Rect.java
package je3.classes;
/**
 * This class represents a rectangle.  Its fields represent the coordinates
 * of the corners of the rectangle.  Its methods define operations that can
 * be performed on Rect objects.
 **/
public class Rect {
    // These are the data fields of the class
    public int x1, y1, x2, y2;

    /**
     * The is the main constructor for the class.  It simply uses its arguments
     * to initialize each of the fields of the new object.  Note that it has
     * the same name as the class, and that it has no return value declared in
     * its signature.
     **/
    public Rect(int x1, int y1, int x2, int y2) {
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
    }

    /**
     * This is another constructor.  It defines itself in terms of the above
     **/
    public Rect(int width, int height) { this(0, 0, width, height); }
    
    /** This is yet another constructor. */
    public Rect( ) { this(0, 0, 0, 0); }

    /** Move the rectangle by the specified amounts */
    public void move(int deltax, int deltay) {
        x1 += deltax; x2 += deltax;
        y1 += deltay; y2 += deltay;
    }

    /** Test whether the specified point is inside the rectangle */
    public boolean isInside(int x, int y) {
        return ((x >= x1)&& (x <= x2)&& (y >= y1)&& (y <= y2));
    }

    /** 
     * Return the union of this rectangle with another.  I.e. return the 
     * smallest rectangle that includes them both.
     **/
    public Rect union(Rect r) {
        return new Rect((this.x1 < r.x1) ? this.x1 : r.x1,
                        (this.y1 < r.y1) ? this.y1 : r.y1,
                        (this.x2 > r.x2) ? this.x2 : r.x2,
                        (this.y2 > r.y2) ? this.y2 : r.y2);
    }
    
    /** 
     * Return the intersection of this rectangle with another. 
     * I.e. return their overlap.
     **/
    public Rect intersection(Rect r) {
        Rect result =  new Rect((this.x1 > r.x1) ? this.x1 : r.x1,
                                (this.y1 > r.y1) ? this.y1 : r.y1,
                                (this.x2 < r.x2) ? this.x2 : r.x2,
                                (this.y2 < r.y2) ? this.y2 : r.y2);
        if (result.x1 > result.x2) { result.x1 = result.x2 = 0; }
        if (result.y1 > result.y2) { result.y1 = result.y2 = 0; }
        return result;
    }

    /**
     * This is a method of our superclass, Object.  We override it so that
     * Rect objects can be meaningfully converted to strings, can be 
     * concatenated to strings with the + operator, and can be passed to 
     * methods like System.out.println( )
     **/
    public String toString( ) {
        return "[" + x1 + "," + y1 + "; " + x2 + "," + y2 + "]";
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Testing the Rect Class
Example 2-2 is a standalone program named RectTest that puts the Rect class of Example 2-1 through its paces. Note the use of the new keyword and the Rect( ) constructor to create new Rect objects. The program uses the . operator to invoke methods of the Rect objects and to access their fields. The test program also relies implicitly on the toString( ) method of Rect when it uses the string concatenation operator (+) to create strings to be displayed to the user.
Example 2-2. RectTest.java
package je3.classes;

/** This class demonstrates how you might use the Rect class */
public class RectTest {
    public static void main(String[  ] args) {
        Rect r1 = new Rect(1, 1, 4, 4);    // Create Rect objects
        Rect r2 = new Rect(2, 3, 5, 6);
        Rect u = r1.union(r2);             // Invoke Rect methods
        Rect i = r2.intersection(r1);
        
        if (u.isInside(r2.x1, r2.y1))   // Use Rect fields and invoke a method
            System.out.println("(" + r2.x1 + "," + r2.y1 +
                               ") is inside the union");
        
        // These lines implicitly call the Rect.toString( ) method
        System.out.println(r1 + " union " + r2 + " = " + u);
        System.out.println(r1 + " intersect " + r2 + " = " + i);
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
A Rect Subclass
Example 2-3 is a simple subclass of the Rect class of Example 2-1. This DrawableRect class inherits the fields and methods of Rect and adds its own method, draw( ), that draws a rectangle using a specified java.awt.Graphics object. (We'll see more of the Graphics object in Chapter 12.) DrawableRect also defines a constructor that simply uses the super keyword to pass its arguments up to the corresponding Rect constructor. Note the use of the extends keyword to indicate that Rect is the superclass of DrawableRect.
Example 2-3. DrawableRect.java
package je3.classes;
/**
 * This is a subclass of Rect that allows itself to be drawn on a screen.
 * It inherits all the fields and methods of Rect
 * It relies on the java.awt.Graphics object to perform the drawing.
 **/
public class DrawableRect extends Rect {
    /** The DrawableRect constructor just invokes the Rect( ) constructor */
    public DrawableRect(int x1, int y1, int x2, int y2) { super(x1,y1,x2,y2); }
    
    /** This is the new method defined by DrawableRect */
    public void draw(java.awt.Graphics g) {
        g.drawRect(x1, y1, (x2 - x1), (y2-y1));
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Another Subclass
Example 2-4 shows another subclass. ColoredRect is a subclass of DrawableRect (see Example 2-3), which makes it a sub-subclass of Rect (see Example 2-1). This class inherits the fields and methods of DrawableRect and of Rect (and of Object, which is the implicit superclass of Rect). ColoredRect adds two new fields that specify the border color and fill color of the rectangle when it is drawn. (These fields are of type java.awt.Color, which we'll learn about in Chapter 12.) The class also defines a new constructor that allows these fields to be initialized. Finally, ColoredRect overrides the draw( ) method of the DrawableRect class. The draw( ) method defined by ColoredRect draws a rectangle using the specified colors, rather than simply using the default colors as the method in DrawableRect did.
Example 2-4. ColoredRect.java
package je3.classes;
import java.awt.*;

/**
 * This class subclasses DrawableRect and adds colors to the rectangle it draws
 **/
public class ColoredRect extends DrawableRect {
    // These are new fields defined by this class. 
    // x1, y1, x2, and y2 are inherited from our super-superclass, Rect.
    protected Color border, fill;
    
    /**
     * This constructor uses super( ) to invoke the superclass constructor, and
     * also does some initialization of its own.
     **/
    public ColoredRect(int x1, int y1, int x2, int y2,
                       Color border, Color fill)
    {
        super(x1, y1, x2, y2);
        this.border = border;
        this.fill = fill;
    }
    
    /**
     * This method overrides the draw( ) method of our superclass so that it
     * can make use of the colors that have been specified.
     **/
    public void draw(Graphics g) {
        g.setColor(fill);
        g.fillRect(x1, y1, (x2-x1), (y2-y1));
        g.setColor(border);
        g.drawRect(x1, y1, (x2-x1), (y2-y1));
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Complex Numbers
Example 2-5 shows the definition of a class that represents complex numbers. You may recall from algebra class that a complex number is the sum of a real number and an imaginary number. The imaginary number i is the square root of -1. This ComplexNumber class defines two double fields, which represent the real and imaginary parts of the number. These fields are declared private, which means they can be used only within the body of the class; they are inaccessible outside the class. Because the fields are inaccessible, the class defines two accessor methods, real( ) and imaginary( ), that simply return their values. This technique of making fields private and defining accessor methods is called encapsulation. Encapsulation hides the implementation of a class from its users, which means that you can change the implementation without it affecting the users.
Notice that the ComplexNumber class doesn't define any methods, other than the constructor, that set the values of its fields. Once a ComplexNumber object is created, the number it represents can never be changed. This property is known as immutability; it is often useful to design objects that are immutable like this.
ComplexNumber defines two add( ) methods and two multiply( ) methods that perform addition and multiplication of complex numbers. The difference between the two versions of each method is that one is an instance method and one is a class, or static, method. Consider the add( ) methods, for example. The instance method adds the value of the current instance of ComplexNumber to another specified ComplexNumber object. The class method doesn't have a current instance; it simply adds the values of two specified ComplexNumber objects. The instance method is invoked through an instance of the class, like this:
ComplexNumber sum = a.add(b);
The class method, however, is invoked through the class itself, rather than through an instance:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Computing Statistics
So far, the classes we've defined have modeled mathematical abstractions like rectangles and complex numbers. It is easy to imagine other objects that model things like a mailing address or a record in a database. This is not a requirement, however: classes do not have to model "things." They merely have to hold some state (i.e., define some fields) and optionally define methods to manipulate that state. Example 2-6 is just this kind of class: it computes simple statistics about a series of numbers. As numbers are passed to the addDatum( ) method, the Averager class updates its internal state so that its other methods can easily return the average and standard deviation of the numbers that have been passed to it so far. Although this Averager class does not model any "thing," we've followed the Java naming convention of