AhmadLang / Java, How To Program, 2004
.pdf
[Page 232]
6.2. Program Modules in Java
Three kinds of modules exist in Javamethods, classes and packages. Java programs are written by combining new methods and classes that the programmer writes with predefined methods and classes available in the Java Application Programming Interface (also referred to as the Java API or Java class library) and in various other class libraries. Related classes are typically grouped into packages so that they can be imported into programs and reused. You will learn how to group your own classes into packages in Chapter 8. The Java API provides a rich collection of predefined classes that contain methods for performing common mathematical calculations, string manipulations, character manipulations, input/output operations, database operations, networking operations, file processing, error checking and many other useful operations. The Java API classes are part of the J2SE Development Kit (JDK) 5.0.
Good Programming Practice 6.1
Familiarize yourself with the rich collection of classes and methods provided by the Java API (java.sun.com/j2se/5.0/docs/api/index.html). In Section 6.8, we present an overview of several common packages. In Appendix G, we explain how to navigate the Java API documentation.
Software Engineering Observation 6.1
Don't try to reinvent the wheel. When possible, reuse Java API classes and methods. This reduces program development time and avoids introducing programming errors.
Methods (called functions or procedures in other programming languages) allow the programmer to modularize a program by separating its tasks into self-contained units. You have declared methods in every program you have written. These methods are sometimes referred to as programmer-declared methods. The actual statements in the method bodies are written only once, reused from perhaps several locations in a program and are hidden from other methods.
There are several motivations for modularizing a program by means of methods. One is the divide-and- conquer approach, which makes program development more manageable by constructing programs from small, simple pieces. Another is software reusabilityusing existing methods as building blocks to create new programs. Often, you can create programs mostly from standardized methods rather than by building customized code. For example, in earlier programs, we did not have to define how to read data values from the keyboardJava provides these capabilities in class Scanner. A third motivation is to avoid repeating code. Dividing a program into meaningful methods makes the program easier to debug and maintain.
Software Engineering Observation 6.2
To promote software reusability, every method should be limited to performing a single, well-defined task, and the name of the method should express that task effectively. Such methods make programs easier to write, debug, maintain and modify.
Error-Prevention Tip 6.1
A small method that performs one task is easier to test and debug than a larger method that performs many tasks.
[Page 233]
Software Engineering Observation 6.3
If you cannot choose a concise name that expresses a method's task, your method might be attempting to perform too many diverse tasks. It is usually best to break such a method into several smaller method declarations.
As you know, a method is invoked by a method call, and when the called method completes its task, it either returns a result or simply control to the caller. An analogy to this program structure is the hierarchical form of management (Figure 6.1). A boss (the caller) asks a worker (the called method) to perform a task and report back (i.e., return) the results after completing the task. The boss method does not know how the worker method performs its designated tasks. The worker may also call other worker methods, unbeknownst to the boss. This "hiding" of implementation details promotes good software engineering. Figure 6.1 shows the boss method communicating with several worker methods in a hierarchical manner. The boss method divides the responsibilities among the various worker methods. Note that worker1 acts as a "boss method" to worker4 and worker5.
Figure 6.1. Hierarchical boss-method/worker-method relationship.
[View full size image]
the statement
System.out.println( Math.sqrt( c + d * f ) );
calculates and prints the square root of 13.0 + 3.0 * 4.0 = 25.0namely, 5.0. Figure 6.2 summarizes several Math class methods. In the figure, x and y are of type double.
Figure 6.2. Math class methods.
(This item is displayed on page 235 in the print version)
Method |
Description |
Example |
|
|
|
|
|
||
abs( x ) |
absolute value of x |
abs( 23.7 ) is 23.7 |
||
|
|
abs( 0.0 ) is 0.0 |
||
|
|
abs( -23.7 ) is 23.7 |
||
ceil( x ) |
rounds x to the smallest integer not less than x |
ceil( 9.2 ) is 10.0 |
||
|
|
ceil( -9.8 ) is -9.0 |
||
cos( x ) |
trigonometric cosine of x (x in radians) |
cos( 0.0 ) is 1.0 |
||
exp( x ) |
exponential method ex |
exp( 1.0 ) is 2.71828 |
||
|
|
exp( 2.0 ) is 7.38906 |
||
floor( x ) |
rounds x to the largest integer not greater than x |
floor( 9.2 ) is 9.0 |
||
|
|
floor( -9.8 ) is -10.0 |
||
log( x ) |
natural logarithm of x (base e) |
log( Math.E ) is 1.0 |
||
|
|
log( Math.E * Math.E ) is 2.0 |
||
max( x, y ) |
larger value of x and y |
max( 2.3, |
12 |
.7 ) is 12.7 |
|
|
max( -2.3, - |
12.7 ) is -2.3 |
|
min( x, y ) |
smaller value of x and y |
min( 2.3, |
12 |
.7 ) is 2.3 |
|
|
min( -2.3, - |
12.7 ) is -12.7 |
|
pow( x, y ) |
x raised to the power y (i.e., x y) |
pow( 2.0, |
7. |
0 ) is 128.0 |
|
|
pow( 9.0, |
0. |
5 ) is 3.0 |
sin( x ) |
trigonometric sine of x (x in radians) |
sin( 0.0 ) is 0.0 |
||
sqrt( x ) |
square root of x |
sqrt( 900.0 ) is 30.0 |
||
tan( x ) |
trigonometric tangent of x (x in radians) |
tan( 0.0 ) is 0.0 |
||
|
|
|
|
|
Math Class Constants PI and E
Class Math also declares two fields that represent commonly used mathematical constants: Math.PI and Math.E. The constant Math.PI (3.14159265358979323846) is the ratio of a circle's circumference to its diameter. The constant Math.E (2.7182818284590452354) is the base value for natural logarithms (calculated with static Math method log). These fields are declared in class Math with the modifiers public, final and static. Making them public allows other programmers to use these fields in their own classes. Any field declared with keyword final is constantits value cannot be changed after the field is initialized. Both PI and E are declared final because their values never change. Making these fields static allows them to be accessed via the class name Math and a dot (.) separator, just like class Math's methods. Recall from Section 3.5 that when each object of a class maintains its own copy of an attribute, the field that represents the attribute is also known as an instance variableeach object (instance) of the class has a separate instance of the variable in memory. There are fields for which each object of a class does not have a separate instance of the field. That is the case with static fields, which are also known as class variables. When objects of a class containing static fields are created, all the objects of that class share one copy of the class's static fields. Together the class variables and instance variables represent the fields of a class. You will learn more about static fields in Section 8.11.
[Page 235]
Why Is Method main Declared static?
Why must main be declared static? When you execute the Java Virtual Machine (JVM) with the java command, the JVM attempts to invoke the main method of the class you specifywhen no objects of the class have been created. Declaring main as static allows the JVM to invoke main without creating an instance of the class. Method main is usually declared with the header:
public static void main( String args[] )
When you execute your application, you specify its class name as an argument to the command java, as in
java ClassName argument1 argument2 ...
The JVM loads the class specified by ClassName and uses that class name to invoke method main. In the preceding command, ClassName is a command-line argument to the JVM that tells it which class to execute. Following the ClassName, you can also specify a list of Strings (separated by spaces) as command-line arguments that the JVM will pass to your application. Such arguments might be used to specify options (e.g., a file name) to run the application. As you will learn in Chapter 7, Arrays, your application can access those command-line arguments and use them to customize the application.
[Page 236]
Additional Comments about Method main
In earlier chapters, every application had one class that contained only main and possibly a second class that was used by main to create and manipulate objects. Actually, any class can contain a main method. In fact, each of our two-class examples could have been implemented as one class. For example, in the application in Fig. 5.9 and Fig. 5.10, method main (lines 616 of Fig. 5.10) could have been taken as is and placed in class GradeBook (Fig. 5.9). You would then execute the application by typing the command java GradeBook in the command windowthe application results would be identical to those of the two-class version. You can place a main method in every class you declare. The JVM invokes the main method only in the class used to execute the application. Some programmers take advantage of this to build a small test program into each class they declare.
Java allows String objects to be created by assembling smaller strings into larger strings using operator + (or the compound assignment operator +=). This is known as string concatenation. When both operands of operator + are String objects, operator + creates a new String object in which the characters of the right operand are placed at the end of those in the left operand. For example, the expression "hello " + "there" creates the String "hello there".
In line 24 of Fig. 6.3, the expression "Maximum is: " + result uses operator + with operands of types String and double. Every primitive value and object in Java has a String representation. When one of the + operator's operands is a String, the other is converted to a String, then the two are concatenated. In line 24, the double value is converted to its String representation and placed at the end of the String "Maximum is: ". If there are any trailing zeros in a double value, these will be discarded when the number is converted to a String. Thus, the number 9.3500 would be represented as 9.35 in the resulting String.
For primitive values used in string concatenation, the primitive values are converted to Strings. If a boolean is concatenated with a String, the boolean is converted to the String "true" or "false". All objects have a method named toString that returns a String representation of the object. When an object is concatenated with a String, the object's toString method is implicitly called to obtain the String representation of the object. You will learn more about method toString in Chapter 7, Arrays.
When a large String literal is typed into a program's source code, programmers sometimes prefer to break that String into several smaller Strings and place them on multiple lines of code for readability. In this case, the Strings can be reassembled using concatenation. We discuss the details of Strings in Chapter 29, Strings, Characters and Regular Expressions.
Common Programming Error 6.2
It is a syntax error to break a String literal across multiple lines in a program. If a String does not fit on one line, split the String into several smaller Strings and use concatenation to form the desired
String.
Common Programming Error 6.3
Confusing the + operator used for string concatenation with the + operator used for addition can lead to strange results. Java evaluates the operands of an operator from left to right. For example, if integer
variable y has the value 5, the expression "y |
+ |
2 |
= " + y + 2 results |
|
in the string "y + 2 = 52", not "y + 2 = |
7", because first the value |
|||
of y (5) is concatenated with the string "y |
+ |
2 |
= |
", then the value 2 |
is concatenated with the new larger string |
"y |
+ |
2 |
= 5". The |
expression "y + 2 = " + (y + 2) produces the desired result "y + 2 = 7".
