1.3. An Example ProgramExample 1-1 shows a Java program to compute factorials.[4] The numbers at the beginning of each line are not part of the program; they are there for ease of reference when we dissect the program line-by-line.
Example 1-1. Factorial.java: A Program to Compute Factorials1 /** 2 * This program computes the factorial of a number 3 */ 4 public class Factorial { // Define a class 5 public static void main(String[] args) { // The program starts here 6 int input = Integer.parseInt(args[0]); // Get the user's input 7 double result = factorial(input); // Compute the factorial 8 System.out.println(result); // Print out the result 9 } // The main() method ends here 10 11 public static double factorial(int x) { // This method computes x! 12 if (x < 0) // Check for bad input 13 return 0.0; // if bad, return 0 14 double fact = 1.0; // Begin with an initial value 15 while(x > 1) { // Loop until x equals 1 16 fact = fact * x; // multiply by x each time 17 x = x - 1; // and then decrement x 18 } // Jump back to start of loop 19 return fact; // Return the result 20 } // factorial() ends here 21 } // The class ends here 1.3.1. Compiling and Running the ProgramBefore we look at how the program works, we must first discuss how to run it. In order to compile and run the program, you need a Java software development kit (SDK) of some sort. Sun Microsystems created the Java language and ships a free Java SDK for its Solaris operating system and for Microsoft Windows (95/98/NT) platforms. At the time of this writing, the current version of Sun's SDK is entitled Java 2 SDK, Standard Edition, Version 1.2.2 and is available for download from http://java.sun.com/products/jdk/1.2/ (Sun's Java SDK is still often called the JDK, even internally). Be sure to get the SDK and not the Java Runtime Environment. The JRE enables you to run existing Java programs, but not to write your own. Sun supports its SDK only on Solaris and Windows platforms. Many other companies have licensed and ported the SDK to their platforms, however. Contact your operating-system vendor to find if a version of the Java SDK is available for your system. Linux users should visit http://www.blackdown.org/. The Sun SDK is not the only Java programming environment you can use. Companies such as Borland, Inprise, Metrowerks, Oracle, Sybase, and Symantec offer commercial products that enable you to write Java programs. This book assumes that you are using Sun's SDK. If you are using a product from some other vendor, be sure to read that vendor's documentation to learn how to compile and run a simple program, like that shown in Example 1-1. Once you have a Java programming environment installed, the first step towards running our program is to type it in. Using your favorite text editor, enter the program as it is shown in Example 1-1. Omit the line numbers, as they are just there for reference. Note that Java is a case-sensitive language, so you must type lowercase letters in lowercase and uppercase letters in uppercase. You'll notice that many of the lines of this program end with semicolons. It is a common mistake to forget these characters, but the program won't work without them, so be careful! If you are not a fast typist, you can omit everything from // to the end of a line. Those are comments ; they are there for your benefit and are ignored by Java.[5]
When writing Java programs, you should use a text editor that saves files in plain-text format, not a word processor that supports fonts and formatting and saves files in a proprietary format. My favorite text editor on Unix systems is emacs. If you use a Windows system, you might use Notepad or WordPad, if you don't have a more specialized programmer's editor. If you are using a commercial Java programming environment, it probably includes an appropriate text editor; read the documentation that came with the product. When you are done entering the program, save it in a file named Factorial.java. This is important; the program will not work if you save it by any other name. After writing a program like this one, the next step is to compile it. With Sun's SDK, the Java compiler is known as javac. javac is a command-line tool, so you can only use it from a terminal window, such as an MS-DOS window on a Windows system or an xterm window on a Unix system. Compile the program by typing the following command line:[6]
C:\> javac Factorial.java If this command prints any error messages, you probably got something wrong when you typed in the program. If it does not print any error messages, however, the compilation has succeeded, and javac creates a file called Factorial.class. This is the compiled version of the program. Once you have compiled a Java program, you must still run it. Unlike some other languages, Java programs are not compiled into native machine language, so they cannot be executed directly by the system. Instead, they are run by another program known as the Java interpreter. In Sun's SDK, the interpreter is a command-line program named, appropriately enough, java. To run the factorial program, type: C:\> java Factorial 4 java is the command to run the Java interpreter, Factorial is the name of the Java program we want the interpreter to run, and 4 is the input data--the number we want the interpreter to compute the factorial of. The program prints a single line of output, telling us that the factorial of 4 is 24: C:\> java Factorial 4 24.0 Congratulations! You've just written, compiled, and run your first Java program. Try running it again to compute the factorials of some other numbers. 1.3.2. Analyzing the ProgramNow that you have run the factorial program, let's analyze it line by line, to see what makes a Java program tick. 1.3.2.1. CommentsThe first three lines of the program are a comment. Java ignores them, but they tell a human programmer what the program does. A comment begins with the characters /* and ends with the characters */. Any amount of text, including multiple lines of text, may appear between these characters. Java also supports another type of comment, which you can see in lines 4 through 21. If the characters // appear in a Java program, Java ignores those characters and any other text that appears between those characters and the end of the line. 1.3.2.2. Defining a classLine 4 is the beginning of the program. It says that we are defining a class named Factorial. This explains why the program had to be stored in a file named Factorial.java. That filename indicates that the file contains Java source code for a class named Factorial. The word public is a modifier ; it says that the class is publicly available and that anyone may use it. The open curly-brace character ({) marks the beginning of the body of the class, which extends all the way to line 21, where we find the matching close curly-brace character (}). The program contains a number of pairs of curly braces; the lines are indented to show the nesting within these braces. A class is the fundamental unit of program structure in Java, so it is not surprising that the first line of our program declares a class. All Java programs are classes, although some programs use many classes instead of just one. Java is an object-oriented programming language, and classes are a fundamental part of the object-oriented paradigm. Each class defines a unique kind of object. Example 1-1 is not really an object-oriented program, however, so I'm not going to go into detail about classes and objects here. That is the topic of Chapter 3, "Object-Oriented Programming in Java". For now, all you need to understand is that a class defines a set of interacting members. Those members may be fields, methods, or other classes. The Factorial class contains two members, both of which are methods. They are described in upcoming sections. 1.3.2.3. Defining a methodLine 5 begins the definition of a method of our Factorial class. A method is a named chunk of Java code. A Java program can call, or invoke, a method to execute the code in it. If you have programmed in other languages, you have probably seen methods before, but they may have been called functions, procedures, or subroutines. The interesting thing about methods is that they have parameters and return values. When you call a method, you pass it some data you want it to operate on, and it returns a result to you. A method is like an algebraic function: y = f(x) Here, the mathematical function f performs some computation on the value represented by x and returns a value, which we represent by y. To return to line 5, the public and static keywords are modifiers. public means the method is publicly accessible; anyone can use it. The meaning of the static modifier is not important here; it is explained in Chapter 3, "Object-Oriented Programming in Java". The void keyword specifies the return value of the method. In this case, it specifies that this method does not have a return value. The word main is the name of the method. main is a special name. When you run the Java interpreter, it reads in the class you specify, then looks for a method named main().[7] When the interpreter finds this method, it starts running the program at that method. When the main() method finishes, the program is done, and the Java interpreter exits. In other words, the main() method is the main entry point into a Java program. It is not actually sufficient for a method to be named main(), however. The method must be declared public static void exactly as shown in line 5. In fact, the only part of line 5 you can change is the word args, which you can replace with any word you want. You'll be using this line in all of your Java programs, so go ahead and commit it to memory now![8]
Following the name of the main() method is a list of method parameters, contained in parentheses. This main() method has only a single parameter. String[] specifies the type of the parameter, which is an array of strings (i.e., a numbered list of strings of text). args specifies the name of the parameter. In the algebraic equation f(x), x is simply a way of referring to an unknown value. args serves the same purpose for the main() method. As we'll see, the name args is used in the body of the method to refer to the unknown value that is passed to the method. As I've just explained, the main() method is a special one that is called by the Java interpreter when it starts running a Java class (program). When you invoke the Java interpreter like this: C:\> java Factorial 4 the string "4" is passed to the main() method as the value of the parameter named args. More precisely, an array of strings containing only one entry, "4", is passed to main(). If we invoke the program like this: C:\> java Factorial 4 3 2 1 then an array of four strings, "4", "3", "2", and "1", are passed to the main() method as the value of the parameter named args. Our program looks only at the first string in the array, so the other strings are ignored. Finally, the last thing on line 5 is an open curly brace. This marks the beginning of the body of the main() method, which continues until the matching close curly brace on line 9. Methods are composed of statements, which the Java interpreter executes in sequential order. In this case, lines 6, 7, and 8 are three statements that compose the body of the main() method. Each statement ends with a semicolon to separate it from the next. This is an important part of Java syntax; beginning programmers often forget the semicolons. 1.3.2.4. Declaring a variable and parsing inputThe first statement of the main() method, line 6, declares a variable and assigns a value to it. In any programming language, a variable is simply a symbolic name for a value. Think back to algebra class again: c2 = a2 + b2The letters a, b, and c are names we use to refer to unknown values. They make this formula (the Pythagorean theorem) a general one that applies to arbitrary values of a, b, and c, not just a specific set like: 52 = 42 + 32A variable in a Java program is exactly the same thing: it is a name we use to refer to a value. More precisely, a variable is a name that refers to a storage space for a value. We often say that a variable holds a value. Line 6 begins with the words int input. This declares a variable named input and specifies that the variable has the type int; that is, it is an integer. Java can work with several different types of values, including integers, real or floating-point numbers, characters (e.g., letters, digits), and strings. Java is a strongly typed language, which means that all variables must have a type specified and can only refer to values of that type. Our input variable always refers to an integer; it cannot refer to a floating point number or a string. Method parameters are also typed. Recall that the args parameter had a type of String[]. Continuing with line 6, the variable declaration int input is followed by the = character. This is the assignment operator in Java; it sets the value of a variable. When reading Java code, don't read = as "equals," but instead read it as "is assigned the value." As we'll see in Chapter 2, "Java Syntax from the Ground Up", there is a different operator for "equals." The value being assigned to our input variable is Integer.parseInt(args[0]). This is a method invocation. This first statement of the main() method invokes another method whose name is Integer.parseInt(). As you might guess, this method "parses" an integer; that is, it converts a string representation of an integer, such as "4", to the integer itself. The Integer.parseInt() method is not part of the Java language, but it is a core part of the Java API or Application Programming Interface. Every Java program can use the powerful set of classes and methods defined by this core API. The second half of this book is a quick-reference that documents that core API. When you call a method, you pass values (called arguments) that are assigned to the corresponding parameters defined by the method, and the method returns a value. The argument passed to Integer.parseInt() is args[0]. Recall that args is the name of the parameter for main(); it specifies an array (or list) of strings. The elements of an array are numbered sequentially, and the first one is always numbered 0. We only care about the first string in the args array, so we use the expression args[0] to refer to that string. Thus, when we invoke the program as shown earlier, line 6 takes the first string specified after the name of the class, "4", and passes it to the method named Integer.parseInt(). This method converts the string to the corresponding integer and returns the integer as its return value. Finally, this returned integer is assigned to the variable named input. 1.3.2.5. Computing the resultThe statement on line 7 is a lot like the statement on line 6. It declares a variable and assigns a value to it. The value assigned to the variable is computed by invoking a method. The variable is named result, and it has a type of double. double means a double-precision floating-point number. The variable is assigned a value that is computed by the factorial() method. The factorial() method, however, is not part of the standard Java API. Instead, it is defined as part of our program, by lines 11 through 19. The argument passed to factorial() is the value referred to by the input variable, which was computed on line 6. We'll consider the body of the factorial() method shortly, but you can surmise from its name that this method takes an input value, computes the factorial of that value, and returns the result. 1.3.2.6. Displaying outputLine 8 simply calls a method named System.out.println(). This commonly used method is part of the core Java API; it causes the Java interpreter to print out a value. In this case, the value that it prints is the value referred to by the variable named result. This is the result of our factorial computation. If the input variable holds the value 4, the result variable holds the value 24, and this line prints out that value. The System.out.println() method does not have a return value, so there is no variable declaration or = assignment operator in this statement, since there is no value to assign to anything. Another way to say this is that, like the main() method of line 5, System.out.println() is declared void. 1.3.2.7. The end of a methodLine 9 contains only a single character, }. This marks the end of the method. When the Java interpreter gets here, it is done executing the main() method, so it stops running. The end of the main() method is also the end of the variable scope for the input and result variables declared within main() and for the args parameter of main(). These variable and parameter names have meaning only within the main() method and cannot be used elsewhere in the program, unless other parts of the program declare different variables or parameters that happen to have the same name. 1.3.2.8. Blank linesLine 10 is a blank line. You can insert blank lines, spaces, and tabs anywhere in a program, and you should use them liberally to make the program readable. A blank line appears here to separate the main() method from the factorial() method that begins on line 11. You'll notice that the program also uses spaces and tabs to indent the various lines of code. This kind of indentation is optional; it emphasizes the structure of the program and greatly enhances the readability of the code. 1.3.2.9. Another methodLine 11 begins the definition of the factorial() method that was used by the main() method. Compare this line to line 5 to note its similarities and differences. The factorial() method has the same public and static modifiers. It takes a single integer parameter, which we call x. Unlike the main() method, which had no return value (void), factorial() returns a value of type double. The open curly brace marks the beginning of the method body, which continues past the nested braces on lines 15 and 18 to line 20, where the matching close curly brace is found. The body of the factorial() method, like the body of the main() method, is composed of statements, which are found on lines 12 through 19. 1.3.2.10. Checking for valid inputIn the main() method, we saw variable declarations, assignments, and method invocations. The statement on line 12 is different. It is an if statement, which executes another statement conditionally. We saw earlier that the Java interpreter executes the three statements of the main() method one after another. It always executes them in exactly that way, in exactly that order. An if statement is a flow-control statement; it can affect the way the interpreter runs a program. The if keyword is followed by a parenthesized expression and a statement. The Java interpreter first evaluates the expression. If it is true, the interpreter executes the statement. If the expression is false, however, the interpreter skips the statement and goes to the next one. The condition for the if statement on line 12 is x < 0. It checks whether the value passed to the factorial() method is less than zero. If it is, this expression is true, and the statement on line 13 is executed. Line 12 does not end with a semicolon because the statement on line 13 is part of the if statement. Semicolons are required only at the end of a statement. Line 13 is a return statement. It says that the return value of the factorial() method is 0.0. return is also a flow-control statement. When the Java interpreter sees a return, it stops executing the current method and returns the specified value immediately. A return statement can stand alone, but in this case, the return statement is part of the if statement on line 12. The indentation of line 13 helps emphasize this fact. (Java ignores this indentation, but it is very helpful for humans who read Java code!) Line 13 is executed only if the expression on line 12 is true. Before we move on, we should pull back a bit and talk about why lines 12 and 13 are necessary in the first place. It is an error to try to compute a factorial for a negative number, so these lines make sure that the input value x is valid. If it is not valid, they cause factorial() to return a consistent invalid result, 0.0. 1.3.2.11. An important variableLine 14 is another variable declaration; it declares a variable named fact of type double and assigns it an initial value of 1.0. This variable holds the value of the factorial as we compute it in the statements that follow. In Java, variables can be declared anywhere; they are not restricted to the beginning of a method or block of code. 1.3.2.12. Looping and computing the factorialLine 15 introduces another type of statement: the while loop. Like an if statement, a while statement consists of a parenthesized expression and a statement. When the Java interpreter sees a while statement, it evaluates the associated expression. If that expression is true, the interpreter executes the statement. The interpreter repeats this process, evaluating the expression and executing the statement if the expression is true, until the expression evaluates to false. The expression on line 15 is x > 1, so the while statement loops while the parameter x holds a value that is greater than 1. Another way to say this is that the loop continues untilx holds a value less than or equal to 1. We can assume from this expression that if the loop is ever going to terminate, the value of x must somehow be modified by the statement that the loop executes. The major difference between the if statement on lines 12-13 and the while loop on lines 15-18 is that the statement associated with the while loop is a compound statement. A compound statement is zero or more statements grouped between curly braces. The while keyword on line 15 is followed by an expression in parentheses and then by an open curly brace. This means that the body of the loop consists of all statements between that opening brace and the closing brace on line 18. Earlier in the chapter, I said that all Java statements end with semicolons. This rule does not apply to compound statements, however, as you can see by the lack of a semicolon at the end of line 18. The statements inside the compound statement (lines 16 and 17) do end with semicolons, of course. The body of the while loop consists of the statements on line 16 and 17. Line 16 multiplies the value of fact by the value of x and stores the result back into fact. Line 17 is similar. It subtracts 1 from the value of x and stores the result back into x. The * character on line 16 is important: it is the multiplication operator. And, as you can probably guess, the - on line 17 is the subtraction operator. An operator is a key part of Java syntax: it performs a computation on one or two operands to produce a new value. Operands and operators combine to form expressions, such as fact * x or x - 1. We've seen other operators in the program. Line 15, for example, uses the greater-than operator (>) in the expression x > 1, which compares the value of the variable x to 1. The value of this expression is a boolean truth value--either true or false, depending on the result of the comparison. To understand this while loop, it is helpful to think like the Java interpreter. Suppose we are trying to compute the factorial of 4. Before the loop starts, fact is 1.0, and x is 4. After the body of the loop has been executed once--after the first iteration--fact is 4.0, and x is 3. After the second iteration, fact is 12.0, and x is 2. After the third iteration, fact is 24.0, and x is 1. When the interpreter tests the loop condition after the third iteration, it finds that x > 1 is no longer true, so it stops running the loop, and the program resumes at line 19. 1.3.2.13. Returning the resultLine 19 is another return statement, like the one we saw on line 13. This one does not return a constant value like 0.0, but instead returns the value of the fact variable. If the value of x passed into the factorial() function is 4, then, as we saw earlier, the value of fact is 24.0, so this is the value returned. Recall that the factorial() method was invoked on line 7 of the program. When this return statement is executed, control returns to line 7, where the return value is assigned to the variable named result. 1.3.3. ExceptionsIf you've made it all the way through the line-by-line analysis of Example 1-1, you are well on your way to understanding the basics of the Java language.[9] It is a simple but nontrivial program that illustrates many of the features of Java. There is one more important feature of Java programming I want to introduce, but it is one that does not appear in the program listing itself. Recall that the program computes the factorial of the number you specify on the command line. What happens if you run the program without specifying a number?
C:\> java Factorial java.lang.ArrayIndexOutOfBoundsException: 0 at Factorial.main(Factorial.java:6) C:\> And what happens if you specify a value that is not a number? C:\> java Factorial ten java.lang.NumberFormatException: ten at java.lang.Integer.parseInt(Integer.java) at java.lang.Integer.parseInt(Integer.java) at Factorial.main(Factorial.java:6) C:\> In both cases, an error occurs or, in Java terminology, an exception is thrown. When an exception is thrown, the Java interpreter prints out a message that explains what type of exception it was and where it occurred (both exceptions above occurred on line 6 ). In the first case, the exception is thrown because there are no strings in the args list, meaning we asked for a nonexistent string with args[0]. In the second case, the exception is thrown because Integer.parseInt() cannot convert the string "ten" to a number. We'll see more about exceptions in Chapter 2, "Java Syntax from the Ground Up" and learn how to handle them gracefully as they occur. Copyright © 2001 O'Reilly & Associates. All rights reserved. |
|