Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

AhmadLang / Java, How To Program, 2004

.pdf
Скачиваний:
630
Добавлен:
31.05.2015
Размер:
51.82 Mб
Скачать

[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]

[Page 233 (continued)]

6.3. static Methods, static Fields and Class Math

As you know, every class provides methods that perform common tasks on objects of the class. For example, to input data from the keyboard, you have called methods on a Scanner object that was initialized in its constructor to obtain input from the standard input stream (System.in). As you will learn in Chapter 14, Files and Streams, you can initialize a Scanner to obtain input from other sources, such as a file on disk. One program could have a Scanner object that inputs information from the standard input stream and a second Scanner that inputs information from a file. Each input method called on the standard input stream Scanner would obtain input from the keyboard, and each input method called on the file Scanner would obtain input from the specified file on disk.

Although most methods execute in response to method calls on specific objects, this is not always the case. Sometimes a method performs a task that does not depend on the contents of any object. Such a method applies to the class in which it is declared as a whole and is known as a static method or a class method. It is not uncommon for a class to contain a group of convenient static methods to perform common tasks. For example, recall that we used static method pow of class Math to raise a value to a power in Fig. 5.6.

[Page 234]

To declare a method as static, place the keyword static before the return type in the method's declaration. You can call any static method by specifying the name of the class in which the method is declared, followed by a dot (.) and the method name, as in

ClassName.methodName( arguments )

We use various Math class methods here to present the concept of static methods. Class Math provides a collection of methods that enable you to perform common mathematical calculations. For example, you can calculate the square root of 900.0 with the static method call

Math.sqrt( 900.0 )

The preceding expression evaluates to 30.0. Method sqrt takes an argument of type double and returns a result of type double. To output the value of the preceding method call in the command window, you might write the statement

System.out.println( Math.sqrt( 900.0 ) );

In this statement, the value that sqrt returns becomes the argument to method println. Note that there was no need to create a Math object before calling method sqrt. Also note that all Math class methods are statictherefore, each is called by preceding the name of the method with the class name Math and a dot (.) separator.

Software Engineering Observation 6.4

Class Math is part of the java.lang package, which is implicitly imported by the compiler, so it is not necessary to import class Math to use its methods.

Method arguments may be constants, variables or expressions. If c = 13.0, d = 3.0 and f = 4.0, then

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.

[Page 236 (continued)]

6.4. Declaring Methods with Multiple Parameters

Chapters 35 presented classes containing simple methods that had at most one parameter. Methods often require more than one piece of information to perform their tasks. We now consider how programmers write their own methods with multiple parameters.

The application in Fig. 6.3 and Fig. 6.4 uses a programmer-declared method called maximum to determine and return the largest of three double values that are input by the user. When the application begins execution, class MaximumFinderTest's main method (lines 711 of Fig. 6.4) creates one object of class MaximumFinder (line 9) and calls the object's determineMaximum method (line 10) to produce the program's output. In class MaximumFinder (Fig. 6.3), lines 1418 of method determineMaximum prompt the user to enter three double values and read them from the user. Line 21 calls method maximum (declared in lines 2841) to determine the largest of the three double values passed as arguments to the method. When method maximum returns the result to line 21, the program assigns maximum's return value to local variable result. Then line 24 outputs the maximum value. At the end of this section, we'll discuss the use of operator + in line 24.

Figure 6.3. Programmer-declared method maximum that has three double parameters.

(This item is displayed on page 237 in the print version)

1// Fig. 6.3: MaximumFinder.java

2// Programmer-declared method maximum.

3import java.util.Scanner;

4

5public class MaximumFinder

6{

7 // obtain three floating-point values and locate the maximum value

8public void determineMaximum()

9{

10// create Scanner for input from command window

11Scanner input = new Scanner( System.in );

12

13// obtain user input

14System.out.print(

15"Enter three floating-point values separated by spaces: " );

16double number1 = input.nextDouble(); // read first double

17double number2 = input.nextDouble(); // read second double

18double number3 = input.nextDouble(); // read third double

19

20// determine the maximum value

21double result = maximum( number1, number2, number3 );

23// display maximum value

24System.out.println( "Maximum is: " + result );

25} // end method determineMaximum

27// returns the maximum of its three double parameters

28public double maximum( double x, double y, double z )

29

{

30

double maximumValue = x; // assume x is the largest to start

31

 

32// determine whether y is greater than maximumValue

33if ( y > maximumValue )

34maximumValue = y;

35

36// determine whether z is greater than maximumValue

37if ( z > maximumValue )

38maximumValue = z;

39

40return maximumValue;

41} // end method maximum

42 } // end class MaximumFinder

Figure 6.4. Application to test class MaximumFinder.

(This item is displayed on page 238 in the print version)

1// Fig. 6.4: MaximumFinderTest.java

2// Application to test class MaximumFinder.

4public class MaximumFinderTest

5{

6// application starting point

7public static void main( String args[] )

8{

9MaximumFinder maximumFinder = new MaximumFinder();

10maximumFinder.determineMaximum();

11} // end main

12} // end class MaximumFinderTest

Enter three floating-point values separated by spaces: 9.35 2.74 5.1 Maximum is: 9.35

Enter three floating-point values separated by spaces: 5.8 12.45 8.32 Maximum is: 12.45

Enter three floating-point values separated by spaces: 6.46 4.12 10.54 Maximum is: 10.54

Consider the declaration of method maximum (lines 2841). Line 28 indicates that the method returns a double value, that the method's name is maximum and that the method requires three double parameters (x, y and z) to accomplish its task. When a method has more than one parameter, the parameters are specified as a comma-separated list. When maximum is called from line 21, the parameter x is initialized with the value of the argument number1, the parameter y is initialized with the value of the argument number2 and the parameter z is initialized with the value of the argument number3. There must be one argument in the method call for each parameter (sometimes called a formal parameter) in the method declaration. Also, each argument must be consistent with the type of the corresponding parameter. For example, a parameter of type double can receive values like 7.35, 22 or 0.03456, but not Strings like "hello". Section 6.7 discusses the argument types that can be provided in a method call for each parameter of a primitive type.

[Page 237]

To determine the maximum value, we begin with the assumption that parameter x contains the largest

value, so line 30 declares local variable maximumValue and initializes it with the value of parameter x. Of course, it is possible that parameter y or z contains the actual largest value, so we must compare each of these values with maximumValue. The if statement at lines 3334 determines whether y is greater than maximumValue. If so, line 34 assigns y to maximumValue. The if statement at lines 3738 determines whether z is greater than maximumValue. If so, line 38 assigns z to maximumValue. At this point the largest of the three values resides in maximumValue, so line 40 returns that value to line 21. When program control returns to the point in the program where maximum was called, maximum's parameters x, y and z no longer exist in memory. Note that methods can return at most one value, but the returned value could be a reference to an object that contains many values.

[Page 238]

Note that result is a local variable in determineMaximum because it is declared in the block that represents the method's body. Variables should be declared as fields of a class only if they are required for use in more than one method of the class or if the program should save their values between calls to the class's methods.

Common Programming Error 6.1

Declaring method parameters of the same type as float x, y instead of float x, float y is a syntax errora type is required for each parameter in the parameter list.

Software Engineering Observation 6.5

A method that has many parameters may be performing too many tasks. Consider dividing the method into smaller methods that perform the separate tasks. As a guideline, try to fit the method header on one line if possible.

Implementing Method maximum by Reusing Method Math.max

Recall from Fig. 6.2 that class Math has a max method that can determine the larger of two values. The entire body of our maximum method could also be implemented with two calls to Math.max, as follows:

return Math.max( x, Math.max( y, z ) );

[Page 239]

The first call to Math.max specifies arguments x and Math.max( y, z ). Before any method can be called, all its arguments must be evaluated to determine their values. If an argument is a method call, the method call must be performed to determine its return value. So, in the preceding statement, Math.max( y, z ) is evaluated first to determine the maximum of y and z. Then the result is passed as the second argument to the other call to Math.max, which returns the larger of its two arguments. Using Math.max in this manner is a good example of software reusewe find the largest of three values by reusing Math.max, which finds the largest of two values. Note how concise this code is compared to lines 3040 of Fig. 6.3.

Assembling Strings with String Concatenation

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".

[Page 240]

6.5. Notes on Declaring and Using Methods

There are three ways to call a method:

1.Using a method name by itself to call another method of the same classsuch as maximum( number1, number2, number3 ) in line 21 of Fig. 6.3.

2.Using a variable that contains a reference to an object, followed by a dot (.) and the method name to call a method of the referenced objectsuch as the method call in line 10 of Fig. 6.4, maximumFinder.determineMaximum(), which calls a method of class MaximumFinder from the main method of MaximumFinderTest.

3.Using the class name and a dot (.) to call a static method of a classsuch as Math.sqrt( 900.0 ) in Section 6.3.

Note that a static method can call only other static methods of the same class directly (i.e., using the method name by itself) and can manipulate only static fields in the same class directly. To access the class's non-static members, a static method must use a reference to an object of the class. Recall that static methods relate to a class as a whole, whereas non-static methods are associated with a specific instance (object) of the class and may manipulate the instance variables of that object. Many objects of a class, each with its own copies of the instance variables, may exist at the same time. Suppose a static method were to invoke a non-static method directly. How would the method know which object's instance variables to manipulate? What would happen if no objects of the class existed at the time the non-static method was invoked? Clearly, such a situation would be problematic. Thus, Java does not allow a static method to access non-static members of the same class directly.

There are three ways to return control to the statement that calls a method. If the method does not return a result, control returns when the program flow reaches the method-ending right brace or when the statement

return;

is executed. If the method returns a result, the statement

return expression;

evaluates the expression, then returns the result to the caller.

Common Programming Error 6.4

Declaring a method outside the body of a class declaration or inside the body of another method is a syntax error.

Common Programming Error 6.5

Omitting the return-value-type in a method declaration is a syntax error.