Objectives
In this appendix you’ll learn:
How static
methods and fields are associated with classes rather than objects.
How the method call/return mechanism is supported by the method-call stack.
How packages group related classes.
To use random-number generation to implement game-playing applications.
How the visibility of declarations is limited to specific regions of programs.
What method overloading is and how to create overloaded methods.
D.3 static
Methods, static
Fields and Class Math
D.4 Declaring Methods with Multiple Parameters
D.5 Notes on Declaring and Using Methods
D.6 Method-Call Stack and Activation Records
D.7 Argument Promotion and Casting
D.9 Introduction to Random-Number Generation
D.9.1 Scaling and Shifting of Random Numbers
D.9.2 Random-Number Repeatability for Testing and Debugging
D.10 Case Study: A Game of Chance; Introducing Enumerations
Self-Review Exercises | Answers to Self-Review Exercises | Exercises
In this appendix, we study methods in more depth. You’ll see that it’s possible to call certain methods, called static
methods, without the need for an object of the class to exist. You’ll learn how to declare a method with more than one parameter. You’ll also learn how Java keeps track of which method is currently executing, how local variables of methods are maintained in memory and how a method knows where to return after it completes execution.
We’ll take a brief diversion into simulation techniques with random-number generation and develop a version of the casino dice game called craps that uses most of the programming techniques you’ve used to this point in the book. In addition, you’ll learn how to declare values that cannot change (i.e., constants) in your programs.
Many of the classes you’ll use or create while developing applications will have more than one method of the same name. This technique, called overloading, is used to implement methods that perform similar tasks for arguments of different types or for different numbers of arguments.
You write Java programs by combining new methods and classes with predefined ones 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’ll learn how to group your own classes into packages in Appendix F. 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 tasks.
Software Engineering Observation D.1
Familiarize yourself with the rich collection of classes and methods provided by the Java API (http://docs.oracle.com/javase/7/docs/api/
) and reuse them when possible. This reduces program development time and avoids introducing programming errors.
Methods (called functions or procedures in some languages) help you modularize a program by separating its tasks into self-contained units. You’ve declared methods in every program you’ve written. The statements in the method bodies are written only once, are hidden from other methods and can be reused from several locations in a program.
One motivation for modularizing a program into methods is the divide-and-conquer approach, which makes program development more manageable by constructing programs from small, simple pieces. Another is software reusability—using 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 define how to read data from the keyboard—Java provides these capabilities in the methods of class Scanner
. A third motivation is to avoid repeating code. Dividing a program into meaningful methods makes the program easier to debug and maintain.
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’s declared as a whole and is known as a static
method or a class method. It’s common for classes to contain 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. C.15. To declare a method as static
, place the keyword static
before the return type in the method’s declaration. For any class imported into your program, you can call the class’s static
methods 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
. There was no need to create a Math
object before calling method sqrt
. Also all Math
class methods are static
—therefore, each is called by preceding its name with the class name Math
and the dot (.
) separator.
Software Engineering Observation D.2
Class Math
is part of the java.lang
package, which is implicitly imported by the compiler, so it’s not necessary to import class Math
to use its methods.
Method arguments may be constants, variables or expressions. Figure D.1 summarizes several Math
class methods. In the figure, x and y are of type double
.
Class Math
declares two fields that represent commonly used mathematical constants—Math.PI and Math.E. Math.PI
(3.141592653589793) is the ratio of a circle’s circumference to its diameter. Math.E
(2.718281828459045) 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 you to use these fields in your own classes. Any field declared with keyword final is constant—its value cannot change after the field is initialized. 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 B.4 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 variable—each 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’s 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 (i.e., static
variables) and instance variables represent the fields of a class. You’ll learn more about static
fields in Section F.10.
When you execute the Java Virtual Machine (JVM) with the java
command, the JVM attempts to invoke the main
method of the class you specify—when 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. 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 String
s (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’ll learn in Appendix E, your application can access those command-line arguments and use them to customize the application.
We now consider how to write your own methods with multiple parameters. Figure D.2 uses a method called maximum
to determine and return the largest of three double
values. In main
, lines 14–18 prompt the user to enter three double
values, then read them from the user. Line 21 calls method maximum
(declared in lines 28–41) to determine the largest of the three values it receives as arguments. 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.
1 // Fig. D.2: MaximumFinder.java
2 // Programmer-declared method maximum with three double parameters.
3 import java.util.Scanner;
4
5 public class MaximumFinder
6 {
7 // obtain three floating-point values and locate the maximum value
8 public static void main( String[] args )
9 {
10 // create Scanner for input from command window
11 Scanner input = new Scanner( System.in );
12
13 // prompt for and input three floating-point values
14 System.out.print(
15 "Enter three floating-point values separated by spaces: " );
16 double number1 = input.nextDouble(); // read first double
17 double number2 = input.nextDouble(); // read second double
18 double number3 = input.nextDouble(); // read third double
19
20 // determine the maximum value
21
22 double result = maximum( number1, number2, number3 );
23 // display maximum value
24 System.out.println( "Maximum is: " + result );
25 } // end main
26
27 // returns the maximum of its three double parameters
28 public static 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
33 if ( y > maximumValue )
34 maximumValue = y;
35
36 // determine whether z is greater than maximumValue
37 if ( z > maximumValue )
38 maximumValue = z;
39
40 return maximumValue;
41 } // end method maximum
42 } // end class MaximumFinder
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
Method maximum
’s declaration begins with keyword public
to indicate that the method is “available to the public”—it can be called from methods of other classes. The keyword static
enables the main
method (another static
method) to call maximum
as shown in line 21 without qualifying the method name with the class name MaximumFinder
—static
methods in the same class can call each other directly. Any other class that uses maximum
must fully qualify the method name with the class name.
In maximum
’s declaration (lines 28–41), line 28 indicates that it returns a double
value, that the its name is maximum
and that it requires three double
parameters (x
, y
and z
) to accomplish its task. Multiple parameters are specified as a comma-separated list. When maximum
is called (line 21), the parameters x
, y
and z
are initialized with the values of arguments number1
, number2
and number3
, respectively. There must be one argument in the method call for each parameter in the method declaration. Also, each argument must be consistent with the type of the corresponding parameter. For example, a double
parameter can receive values like 7.35, 22 or —0.03456, but not String
s like "hello"
nor the boolean
values true
or false
.
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’s 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 33–34 determines whether y
is greater than maximumValue
. If so, line 34 assigns y
to maximumValue
. The if
statement at lines 37–38 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.
Software Engineering Observation D.3
Variables should be declared as fields only if they’re 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.
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 ) );
The first call to Math.max
specifies arguments x
and Math.max( y, z )
. Before any method can be called, 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 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.
Java allows you to assemble String
objects into larger strings by using operators +
or +=
. 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—e.g., the expression "hello " + "there"
creates the String "hello there"
.
In line 24 of Fig. D.2, 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
—for example 9.3500 would be represented as 9.35.
Primitive values used in String
concatenation are converted to String
s. A boolean
concatenated with a String
is converted to the String "true"
or "false"
. All objects have a toString
method 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. ToString
can be called explicitly.
It’s a syntax error to break a String
literal across lines. If necessary, you can split a String
into several smaller String
s and use concatenation to form the desired String
.
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 to the string "y + 2 = "
, then the value 2
is concatenated to the new larger string "y + 2 = 5"
. The expression "y + 2 = " + (y + 2)
produces the desired result "y + 2 = 7"
.
There are three ways to call a method:
1. Using a method name by itself to call another method of the same class—such as maximum(number1, number2, number3)
in line 21 of Fig. D.2.
2. Using a variable that contains a reference to an object, followed by a dot (.
) and the method name to call a non-static
method of the referenced object—such as the method call in line 13 of Fig. C.3, myGradeBook.displayMessage()
, which calls a method of class GradeBook
from the main
method of GradeBookTest
.
3. Using the class name and a dot (.
) to call a static
method of a class—such as Math.sqrt(900.0)
in Section D.3.
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
variables 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. 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? 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.
Declaring a method outside the body of a class declaration or inside the body of another method is a syntax error.
Redeclaring a parameter as a local variable in the method’s body is a compilation error.
To understand how Java performs method calls, we first need to consider a data structure (i.e., collection of related data items) known as a stack. You can think of a stack as analogous to a pile of dishes. When a dish is placed on the pile, it’s normally placed at the top (referred to as pushing the dish onto the stack). Similarly, when a dish is removed from the pile, it’s always removed from the top (referred to as popping the dish off the stack). Stacks are known as last-in, first-out (LIFO) data structures—the last item pushed (inserted) on the stack is the first item popped (removed) from the stack.
When a program calls a method, the called method must know how to return to its caller, so the return address of the calling method is pushed onto the program-execution stack (sometimes referred to as the method-call stack). If a series of method calls occurs, the successive return addresses are pushed onto the stack in last-in, first-out order so that each method can return to its caller.
The program-execution stack also contains the memory for the local variables used in each invocation of a method during a program’s execution. This data, stored as a portion of the program-execution stack, is known as the activation record or stack frame of the method call. When a method call is made, the activation record for that method call is pushed onto the program-execution stack. When the method returns to its caller, the activation record for this method call is popped off the stack and those local variables are no longer known to the program. If a local variable holding a reference to an object is the only variable in the program with a reference to that object, then, when the activation record containing that local variable is popped off the stack, the object can no longer be accessed by the program and will eventually be deleted from memory by the JVM during “garbage collection.” We discuss garbage collection in Section F.9.
Of course, a computer’s memory is finite, so only a certain amount can be used to store activation records on the program-execution stack. If more method calls occur than can have their activation records stored, an error known as a stack overflow occurs.
Another important feature of method calls is argument promotion—converting an argument’s value, if possible, to the type that the method expects to receive in its corresponding parameter. For example, a program can call Math
method sqrt
with an int
argument even though a double
argument is expected. The statement
System.out.println( Math.sqrt( 4 ) );
correctly evaluates Math.sqrt(4)
and prints the value 2.0
. The method declaration’s parameter list causes Java to convert the int
value 4
to the double
value 4.0
before passing the value to method sqrt
. Such conversions may lead to compilation errors if Java’s promotion rules are not satisfied. These rules specify which conversions are allowed—that is, which ones can be performed without losing data. In the sqrt
example above, an int
is converted to a double
without changing its value. However, converting a double
to an int
truncates the fractional part of the double
value—thus, part of the value is lost. Converting large integer types to small integer types (e.g., long
to int
, or int
to short
) may also result in changed values.
The promotion rules apply to expressions containing values of two or more primitive types and to primitive-type values passed as arguments to methods. Each value is promoted to the “highest” type in the expression. Actually, the expression uses a temporary copy of each value—the types of the original values remain unchanged. Figure D.3 lists the primitive types and the types to which each can be promoted. The valid promotions for a given type are always to a type higher in the table. For example, an int
can be promoted to the higher types long
, float
and double
.
Converting values to types lower in the table of Fig. D.3 will result in different values if the lower type cannot represent the value of the higher type (e.g., the int
value 2000000 cannot be represented as a short
, and any floating-point number with digits after its decimal point cannot be represented in an integer type such as long
, int
or short
). Therefore, in cases where information may be lost due to conversion, the Java compiler requires you to use a cast operator (introduced in Section C.9) to explicitly force the conversion to occur—otherwise a compilation error occurs. This enables you to “take control” from the compiler. You essentially say, “I know this conversion might cause loss of information, but for my purposes here, that’s fine.” Suppose method square
calculates the square of an integer and thus requires an int
argument. To call square
with a double
argument named doubleValue
, we would be required to write the method call as
square( (int) doubleValue )
This method call explicitly casts (converts) a copy of variable doubleValue
’s value to an integer for use in method square
. Thus, if doubleValue
’s value is 4.5
, the method receives the value 4
and returns 16
, not 20.25
.
As you’ve seen, Java contains many predefined classes that are grouped into categories of related classes called packages. Together, these are known as the Java Application Programming Interface (Java API), or the Java class library. A great strength of Java is the Java API’s thousands of classes. Some key Java API packages used in this book’s appendices are described in Fig. D.4, which represents only a small portion of the reusable components in the Java API.
The set of packages available in Java is quite large. In addition to those summarized in Fig. D.4, Java includes packages for complex graphics, advanced graphical user interfaces, printing, advanced networking, security, database processing, multimedia, accessibility (for people with disabilities), concurrent programming, cryptography, XML processing and many other capabilities.
You can locate additional information about a predefined Java class’s methods in the Java API documentation at http://docs.oracle.com/javase/7/docs/api/
. When you visit this site, click the Index link to see an alphabetical listing of all the classes and methods in the Java API. Locate the class name and click its link to see the online description of the class. Click the METHOD link to see a table of the class’s methods. Each static
method will be listed with the word “static
” preceding its return type.
We now take a brief diversion into a popular type of programming application—simulation and game playing. In this and the next section, we develop a nicely structured game-playing program with multiple methods. The program uses most of the control statements presented thus far in the appendices and introduces several new programming concepts.
Random numbers can be introduced in a program via an object of class Random (package java.util
) or via the static
method random
of class Math
. A Random
object can produce random boolean
, byte
, float
, double
, int
, long
and Gaussian values, whereas Math
method random
can produce only double
values in the range 0.0
≤ x < 1.0
, where x is the value returned by method random
. In the next several examples, we use objects of class Random
to produce random values. We discuss only random int
values here. For more information on the Random
class, see docs.oracle.com/javase/7/docs/api/java/util/Random.html
.
A new random-number generator object can be created as follows:
Random randomNumbers = new Random();
Consider the following statement:
int randomValue = randomNumbers.nextInt();
Random
method nextInt generates a random int
value in the range —2,147,483,648 to +2,147,483,647, inclusive. If it truly produces values at random, then every value in the range should have an equal chance (or probability) of being chosen each time nextInt
is called. The numbers are actually pseudorandom numbers—a sequence of values produced by a complex mathematical calculation. The calculation uses the current time of day (which, of course, changes constantly) to seed the random-number generator such that each execution of a program yields a different sequence of random values.
The range of values produced directly by method nextInt
generally differs from the range of values required in a particular Java application. For example, a program that simulates coin tossing might require only 0 for “heads” and 1 for “tails.” A program that simulates the rolling of a six-sided die might require random integers in the range 1–6. A program that randomly predicts the next type of spaceship (out of four possibilities) that will fly across the horizon in a video game might require random integers in the range 1–4. For cases like these, class Random
provides another version of method nextInt
that receives an int
argument and returns a value from 0 up to, but not including, the argument’s value. For example, for coin tossing, the following statement returns 0 or 1.
int randomValue = randomNumbers.nextInt( 2 );
To demonstrate random numbers, let’s show to simulate rolling a six-sided die. We begin by using nextInt
to produce random values in the range 0–5, as follows:
face = randomNumbers.nextInt( 6 );
The argument 6
—called the scaling factor—represents the number of unique values that nextInt
should produce (in this case six—0, 1, 2, 3, 4 and 5). This manipulation is called scaling the range of values produced by Random
method nextInt
.
A six-sided die has the numbers 1–6 on its faces, not 0–5. So we shift the range of numbers produced by adding a shifting value—in this case 1—to our previous result, as in
face = 1 + randomNumbers.nextInt( 6 );
The shifting value (1
) specifies the first value in the desired range of random integers. The preceding statement assigns face
a random integer in the range 1–6. The numbers produced by nextInt
occur with approximately equal likelihood.
The preceding statement always assigns to variable face
an integer in the range 1
≤ face
≤ 6
. The width of this range (i.e., the number of consecutive integers in the range) is 6
, and the starting number in the range is 1
. The width of the range is determined by the number 6
that’s passed as an argument to Random
method nextInt
, and the starting number of the range is the number 1
that’s added to the result of calling nextInt
. We can generalize this result as
number = shiftingValue + randomNumbers.nextInt( scalingFactor );
where shiftingValue specifies the first number in the desired range of consecutive integers and scalingFactor specifies how many numbers are in the range.
It’s also possible to choose integers at random from sets of values other than ranges of consecutive integers. For example, to obtain a random value from the sequence 2, 5, 8, 11 and 14, you could use the statement
number = 2 + 3 * randomNumbers.nextInt( 5 );
In this case, randomNumbers.nextInt(5)
produces values in the range 0–4. Each value produced is multiplied by 3 to produce a number in the sequence 0, 3, 6, 9 and 12. We add 2 to that value to shift the range of values and obtain a value from the sequence 2, 5, 8, 11 and 14. We can generalize this result as
number = shiftingValue +
differenceBetweenValues * randomNumbers.nextInt( scalingFactor );
where shiftingValue specifies the first number in the desired range of values, differenceBetweenValues represents the constant difference between consecutive numbers in the sequence and scalingFactor specifies how many numbers are in the range.
Class Random
’s methods actually generate pseudorandom numbers based on complex mathematical calculations—the sequence of numbers appears to be random. The calculation that produces the numbers uses the time of day as a seed value to change the sequence’s starting point. Each new Random
object seeds itself with a value based on the computer system’s clock at the time the object is created, enabling each execution of a program to produce a different sequence of random numbers.
When debugging an application, it’s often useful to repeat the exact same sequence of pseudorandom numbers during each execution of the program. This repeatability enables you to prove that your application is working for a specific sequence of random numbers before you test it with different sequences of random numbers. When repeatability is important, you can create a Random
object as follows:
Random randomNumbers = new Random( seedValue );
The seedValue
argument (of type long
) seeds the random-number calculation. If the same seedValue
is used every time, the Random
object produces the same sequence of numbers. You can set a Random
object’s seed at any time during program execution by calling the object’s set
method, as in
randomNumbers.set( seedValue );
While developing a program, create the Random
object with a specific seed value to produce a repeatable sequence of numbers each time the program executes. If a logic error occurs, fix the error and test the program again with the same seed value—this allows you to reconstruct the same sequence of numbers that caused the error. Once the logic errors have been removed, create the Random
object without using a seed value, causing the Random
object to generate a new sequence of random numbers each time the program executes.
A popular game of chance is a dice game known as craps, which is played in casinos and back alleys throughout the world. The rules of the game are straightforward:
You roll two dice. Each die has six faces, which contain one, two, three, four, five and six spots, respectively. After the dice have come to rest, the sum of the spots on the two upward faces is calculated. If the sum is 7 or 11 on the first throw, you win. If the sum is 2, 3 or 12 on the first throw (called “craps”), you lose (i.e., the “house” wins). If the sum is 4, 5, 6, 8, 9 or 10 on the first throw, that sum becomes your “point.” To win, you must continue rolling the dice until you “make your point” (i.e., roll that same point value). You lose by rolling a 7 before making your point.
Figure D.5 simulates the game of craps, using methods to implement the game’s logic. The main
method (lines 21–65) calls the rollDice
method (lines 68–81) as necessary to roll the dice and compute their sum. The sample outputs show winning and losing on the first roll, and winning and losing on a subsequent roll.
1 // Fig. D.5: Craps.java
2 // Craps class simulates the dice game craps.
3 import java.util.Random;
4
5 public class Craps
6 {
7 // create random number generator for use in method rollDice
8 private static final Random randomNumbers = new Random();
9
10 // enumeration with constants that represent the game status
11 private enum Status { CONTINUE, WON, LOST };
12
13 // constants that represent common rolls of the dice
14 private static final int SNAKE_EYES = 2;
15 private static final int TREY = 3;
16 private static final int SEVEN = 7;
17 private static final int YO_LEVEN = 11;
18 private static final int BOX_CARS = 12;
19
20 // plays one game of craps
21 public static void main( String[] args )
22 {
23 int myPoint = 0; // point if no win or loss on first roll
24 Status gameStatus; // can contain CONTINUE, WON or LOST
25
26 int sumOfDice = rollDice(); // first roll of the dice
27
28 // determine game status and point based on first roll
29 switch ( sumOfDice )
30 {
31 case SEVEN: // win with 7 on first roll
32 case YO_LEVEN: // win with 11 on first roll
33 gameStatus = Status.WON;
34 break;
35 case SNAKE_EYES: // lose with 2 on first roll
36 case TREY: // lose with 3 on first roll
37 case BOX_CARS: // lose with 12 on first roll
38 gameStatus = Status.LOST;
39 break;
40 default: // did not win or lose, so remember point
41 gameStatus = Status.CONTINUE; // game is not over
42 myPoint = sumOfDice; // remember the point
43 System.out.printf( "Point is %d
", myPoint );
44 break; // optional at end of switch
45 } // end switch
46
47 // while game is not complete
48 while ( gameStatus == Status.CONTINUE ) // not WON or LOST
49 {
50 sumOfDice = rollDice(); // roll dice again
51
52 // determine game status
53 if ( sumOfDice == myPoint ) // win by making point
54 gameStatus = Status.WON;
55 else
56 if ( sumOfDice == SEVEN ) // lose by rolling 7 before point
57 gameStatus = Status.LOST;
58 } // end while
59
60 // display won or lost message
61 if ( gameStatus == Status.WON )
62 System.out.println( "Player wins" );
63 else
64 System.out.println( "Player loses" );
65 } // end main
66
67 // roll dice, calculate sum and display results
68 public static int rollDice()
69 {
70 // pick random die values
71 int die1 = 1 + randomNumbers.nextInt( 6 ); // first die roll
72 int die2 = 1 + randomNumbers.nextInt( 6 ); // second die roll
73
74 int sum = die1 + die2; // sum of die values
75
76 // display results of this roll
77 System.out.printf( "Player rolled %d + %d = %d
",
78 die1, die2, sum );
79
80 return sum; // return sum of dice
81 } // end method rollDice
82 } // end class Craps
Player rolled 5 + 6 = 11
Player wins
Player rolled 5 + 4 = 9
Point is 9
Player rolled 4 + 2 = 6
Player rolled 3 + 6 = 9
Player wins
Player rolled 1 + 2 = 3
Player loses
Player rolled 2 + 6 = 8
Point is 8
Player rolled 5 + 1 = 6
Player rolled 2 + 1 = 3
Player rolled 1 + 6 = 7
Player loses
In the rules of the game, the player must roll two dice on the first roll and must do the same on all subsequent rolls. We declare method rollDice
(Fig. D.5, lines 68–81) to roll the dice and compute and print their sum. Method rollDice
is declared once, but it’s called from two places (lines 26 and 50) in main
, which contains the logic for one complete game of craps. Method rollDice
takes no arguments, so it has an empty parameter list. Each time it’s called, rollDice
returns the sum of the dice, so the return type int
is indicated in the method header (line 68). Although lines 71 and 72 look the same (except for the die names), they do not necessarily produce the same result. Each of these statements produces a random value in the range 1–6. Variable randomNumbers
(used in lines 71–72) is not declared in the method. Instead it’s declared as a private static final
variable of the class and initialized in line 8. This enables us to create one Random
object that’s reused in each call to rollDice
. If there were a program that contained multiple instances of class Craps
, they’d all share this one Random
object.
The game is reasonably involved. The player may win or lose on the first roll, or may win or lose on any subsequent roll. Method main
(lines 21–65) uses local variable myPoint
(line 23) to store the “point” if the player does not win or lose on the first roll, local variable gameStatus
(line 24) to keep track of the overall game status and local variable sumOfDice
(line 26) to hold the sum of the dice for the most recent roll. Variable myPoint
is initialized to 0
to ensure that the application will compile. If you do not initialize myPoint
, the compiler issues an error, because myPoint
is not assigned a value in every case
of the switch
statement, and thus the program could try to use myPoint
before it’s assigned a value. By contrast, gameStatus
is assigned a value in every case
of the switch
statement—thus, it’s guaranteed to be initialized before it’s used and does not need to be initialized.
Local variable gameStatus
(line 24) is declared to be of a new type called Status
(declared at line 11). Type Status
is a private
member of class Craps
, because Status
will be used only in that class. Status
is a type called an enumeration, which, in its simplest form, declares a set of constants represented by identifiers. An enumeration is a special kind of class that’s introduced by the keyword enum and a type name (in this case, Status
). As with classes, braces delimit an enum
declaration’s body. Inside the braces is a comma-separated list of enumeration constants, each representing a unique value. The identifiers in an enum
must be unique. You’ll learn more about enumerations in Appendix E.
It’s a convention to use only uppercase letters in the names of enumeration constants. This makes them stand out and reminds you that they are not variables.
Variables of type Status
can be assigned only the three constants declared in the enumeration (line 11) or a compilation error will occur. When the game is won, the program sets local variable gameStatus
to Status.WON
(lines 33 and 54). When the game is lost, the program sets local variable gameStatus
to Status.LOST
(lines 38 and 57). Otherwise, the program sets local variable gameStatus
to Status.CONTINUE
(line 41) to indicate that the game is not over and the dice must be rolled again.
Using enumeration constants (like Status.WON
, Status.LOST
and Status.CONTINUE
) rather than literal values (such as 0, 1 and 2) makes programs easier to read and maintain.
Line 26 in main
calls rollDice
, which picks two random values from 1 to 6, displays the values of the first die, the second die and their sum, and returns the sum. Method main
next enters the switch
statement (lines 29–45), which uses the sumOfDice
value from line 26 to determine whether the game has been won or lost, or should continue with another roll. The values that result in a win or loss on the first roll are declared as public static final int
constants in lines 14–18. The identifier names use casino parlance for these sums. These constants, like enum
constants, are declared by convention with all capital letters, to make them stand out in the program. Lines 31–34 determine whether the player won on the first roll with SEVEN
(7
) or YO_LEVEN
(11
). Lines 35–39 determine whether the player lost on the first roll with SNAKE_EYES
(2
), TREY
(3
), or BOX_CARS
(12
). After the first roll, if the game is not over, the default
case (lines 40–44) sets gameStatus
to Status.CONTINUE
, saves sumOfDice
in myPoint
and displays the point.
If we’re still trying to “make our point” (i.e., the game is continuing from a prior roll), lines 48–58 execute. Line 50 rolls the dice again. If sumOfDice
matches myPoint
(line 53), line 54 sets gameStatus
to Status.WON
, then the loop terminates because the game is complete. If sumOfDice
is SEVEN
(line 56), line 57 sets gameStatus
to Status.LOST
, and the loop terminates because the game is complete. When the game completes, lines 61–64 display a message indicating whether the player won or lost, and the program terminates.
The program uses the various program-control mechanisms we’ve discussed. The Craps
class uses two methods—main
and rollDice
(called twice from main
)—and the switch
, while
, if
...else
and nested if
control statements. Note also the use of multiple case
labels in the switch
statement to execute the same statements for sums of SEVEN
and YO_LEVEN
(lines 31–32) and for sums of SNAKE_EYES
, TREY
and BOX_CARS
(lines 35–37).
You might be wondering why we declared the sums of the dice as public final static int
constants rather than as enum
constants. The reason is that the program must compare the int
variable sumOfDice
(line 26) to these constants to determine the outcome of each roll. Suppose we declared enum Sum
containing constants (e.g., Sum.SNAKE_EYES
) representing the five sums used in the game, then used these constants in the switch
statement (lines 29–45). Doing so would prevent us from using sumOfDice
as the switch
statement’s controlling expression, because Java does not allow an int
to be compared to an enumeration constant. To achieve the same functionality as the current program, we would have to use a variable currentSum
of type Sum
as the switch
’s controlling expression. Unfortunately, Java does not provide an easy way to convert an int
value to a particular enum
constant. This could be done with a separate switch
statement. Clearly this would be cumbersome and not improve the program’s readability (thus defeating the purpose of using an enum
).
You’ve seen declarations of various Java entities, such as classes, methods, variables and parameters. Declarations introduce names that can be used to refer to such Java entities. The scope of a declaration is the portion of the program that can refer to the declared entity by its name. Such an entity is said to be “in scope” for that portion of the program. This section introduces several important scope issues.
The basic scope rules are as follows:
1. The scope of a parameter declaration is the body of the method in which the declaration appears.
2. The scope of a local-variable declaration is from the point at which the declaration appears to the end of that block.
3. The scope of a local-variable declaration that appears in the initialization section of a for
statement’s header is the body of the for
statement and the other expressions in the header.
4. A method or field’s scope is the entire body of the class. This enables non-static
methods of a class to use the fields and other methods of the class.
Any block may contain variable declarations. If a local variable or parameter in a method has the same name as a field of the class, the field is “hidden” until the block terminates execution—this is called shadowing. In Appendix F, we discuss how to access shadowed fields.
Use different names for fields and local variables to help prevent subtle logic errors that occur when a method is called and a local variable of the method shadows a field in the class.
Figure D.6 demonstrates scoping issues with fields and local variables. Line 7 declares and initializes the field x
to 1
. This field is shadowed (hidden) in any block (or method) that declares a local variable named x
. Method main
(lines 11–23) declares a local variable x
(line 13) and initializes it to 5
. This local variable’s value is output to show that the field x
(whose value is 1
) is shadowed in main
. The program declares two other methods—useLocalVariable
(lines 26–35) and useField
(lines 38–45)—that each take no arguments and return no results. Method main
calls each method twice (lines 17–20). Method useLocalVariable
declares local variable x
(line 28). When useLocalVariable
is first called (line 17), it creates local variable x
and initializes it to 25
(line 28), outputs the value of x
(lines 30–31), increments x
(line 32) and outputs the value of x
again (lines 33–34). When uselLocalVariable
is called a second time (line 19), it recreates local variable x
and reinitializes it to 25
, so the output of each useLocalVariable
call is identical.
1 // Fig. D.6: Scope.java
2 // Scope class demonstrates field and local variable scopes.
3
4 public class Scope
5 {
6 // field that is accessible to all methods of this class
7 private static int x = 1;
8
9 // method main creates and initializes local variable x
10 // and calls methods useLocalVariable and useField
11 public static void main( String[] args )
12 {
13 int x = 5; // method's local variable x shadows field x
14
15 System.out.printf( "local x in main is %d
", x );
16
17 useLocalVariable(); // useLocalVariable has local x
18 useField(); // useField uses class Scope's field x
19 useLocalVariable(); // useLocalVariable reinitializes local x
20 useField(); // class Scope's field x retains its value
21
22 System.out.printf( "
local x in main is %d
", x );
23 } // end main
24
25 // create and initialize local variable x during each call
26 public static void useLocalVariable()
27 {
28 int x = 25; // initialized each time useLocalVariable is called
29
30 System.out.printf(
31 "
local x on entering method useLocalVariable is %d
", x );
32 ++x; // modifies this method's local variable x
33 System.out.printf(
34 "local x before exiting method useLocalVariable is %d
", x );
35 } // end method useLocalVariable
36
37 // modify class Scope's field x during each call
38 public static void useField()
39 {
40 System.out.printf(
41 "
field x on entering method useField is %d
", x );
42 x *= 10; // modifies class Scope's field x
43 System.out.printf(
44 "field x before exiting method useField is %d
", x );
45 } // end method useField
46 } // end class Scope
local x in main is 5
local x on entering method useLocalVariable is 25
local x before exiting method useLocalVariable is 26
field x on entering method useField is 1
field x before exiting method useField is 10
local x on entering method useLocalVariable is 25
local x before exiting method useLocalVariable is 26
field x on entering method useField is 10
field x before exiting method useField is 100
local x in main is 5
Method useField
does not declare any local variables. Therefore, when it refers to x
, field x
(line 7) of the class is used. When method useField
is first called (line 18), it outputs the value (1
) of field x
(lines 40–41), multiplies the field x
by 10
(line 42) and outputs the value (10
) of field x
again (lines 43–44) before returning. The next time method useField
is called (line 20), the field has its modified value (10
), so the method outputs 10
, then 100
. Finally, in method main
, the program outputs the value of local variable x
again (line 22) to show that none of the method calls modified main
’s local variable x
, because the methods all referred to variables named x
in other scopes.
Methods of the same name can be declared in the same class, as long as they have different sets of parameters (determined by the number, types and order of the parameters)—this is called method overloading. When an overloaded method is called, the compiler selects the appropriate method by examining the number, types and order of the arguments in the call. Method overloading is commonly used to create several methods with the same name that perform the same or similar tasks, but on different types or different numbers of arguments. For example, Math
methods abs
, min
and max
(summarized in Section D.3) are overloaded with four versions each:
1. One with two double
parameters.
2. One with two float
parameters.
3. One with two int
parameters.
4. One with two long
parameters.
Our next example demonstrates declaring and invoking overloaded methods. We demonstrate overloaded constructors in Appendix F.
Class MethodOverload
(Fig. D.7) includes two overloaded versions of method square
—one that calculates the square of an int
(and returns an int
) and one that calculates the square of a double
(and returns a double
). Although these methods have the same name and similar parameter lists and bodies, think of them simply as different methods. It may help to think of the method names as “square
of int
” and “square
of double
,” respectively.
1 // Fig. D.7: MethodOverload.java
2 // Overloaded method declarations.
3
4 public class MethodOverload
5 {
6 // test overloaded square methods
7 public static void main( String[] args )
8 {
9 System.out.printf( "Square of integer 7 is %d
", square( 7 ) );
10 System.out.printf( "Square of double 7.5 is %f
", square( 7.5 ) );
11 } // end main
12
13 // square method with int argument
14 public static int square( int intValue )
15 {
16 System.out.printf( "
Called square with int argument: %d
",
17 intValue );
18 return intValue * intValue;
19 } // end method square with int argument
20
21 // square method with double argument
22 public static double square( double doubleValue )
23 {
24 System.out.printf( "
Called square with double argument: %f
",
25 doubleValue );
26 return doubleValue * doubleValue;
27 } // end method square with double argument
28 } // end class MethodOverload
Called square with int argument: 7
Square of integer 7 is 49
Called square with double argument: 7.500000
Square of double 7.5 is 56.250000
Line 9 invokes method square
with the argument 7
. Literal integer values are treated as type int
, so the method call in line 9 invokes the version of square
at lines 14–19 that specifies an int
parameter. Similarly, line 10 invokes method square
with the argument 7.5
. Literal floating-point values are treated as type double
, so the method call in line 10 invokes the version of square
at lines 22–27 that specifies a double
parameter. Each method first outputs a line of text to prove that the proper method was called in each case. The values in lines 10 and 24 are displayed with the format specifier %f
. We did not specify a precision in either case. By default, floating-point values are displayed with six digits of precision if the precision is not specified in the format specifier.
The compiler distinguishes overloaded methods by their signature—a combination of the method’s name and the number, types and order of its parameters. If the compiler looked only at method names during compilation, the code in Fig. D.7 would be ambiguous—the compiler would not know how to distinguish between the two square
methods (lines 14–19 and 22–27). Internally, the compiler uses longer method names that include the original method name, the types of each parameter and the exact order of the parameters to determine whether the methods in a class are unique in that class.
For example, in Fig. D.7, the compiler might use the logical name “square
of int
” for the square
method that specifies an int
parameter and “square
of double
” for the square
method that specifies a double
parameter (the actual names the compiler uses are messier). If method1
’s declaration begins as
void method1( int a, float b )
then the compiler might use the logical name “method1
of int
and float
.” If the parameters are specified as
void method1( float a, int b )
then the compiler might use the logical name “method1
of float
and int
.” The order of the parameter types is important—the compiler considers the preceding two method1
headers to be distinct.
In discussing the logical names of methods used by the compiler, we did not mention the return types of the methods. Method calls cannot be distinguished by return type. If you had overloaded methods that differed only by their return types and you called one of the methods in a standalone statement as in:
square( 2 );
the compiler would not be able to determine the version of the method to call, because the return value is ignored. When two methods have the same signature and different return types, the compiler issues an error message indicating that the method is already defined in the class. Overloaded methods can have different return types if the methods have different parameter lists. Also, overloaded methods need not have the same number of parameters.
Declaring overloaded methods with identical parameter lists is a compilation error regardless of whether the return types are different.
In this appendix, you learned more about method declarations. You also learned the difference between non-static
and static
methods and how to call static
methods by preceding the method name with the name of the class in which it appears and the dot (.
) separator. You learned how to use operators +
and +=
to perform string concatenations. We discussed how the method-call stack and activation records keep track of the methods that have been called and where each method must return to when it completes its task. We also discussed Java’s promotion rules for converting implicitly between primitive types and how to perform explicit conversions with cast operators. Next, you learned about some of the commonly used packages in the Java API.
You saw how to declare named constants using both enum
types and public static final
variables. You used class Random
to generate random numbers for simulations. You also learned about the scope of fields and local variables in a class. Finally, you learned that multiple methods in one class can be overloaded by providing methods with the same name and different signatures. Such methods can be used to perform the same or similar tasks using different types or different numbers of parameters.
In Appendix E, you’ll learn how to maintain lists and tables of data in arrays. You’ll see a more elegant implementation of the application that rolls a die 6,000,000 times and two enhanced versions of our GradeBook
case study that you studied in Appendices B–C. You’ll also learn how to access an application’s command-line arguments that are passed to method main
when an application begins execution.
D.1 Fill in the blanks in each of the following statements:
a) A method is invoked with a(n) __________.
b) A variable known only within the method in which it’s declared is called a(n) __________.
c) The __________ statement in a called method can be used to pass the value of an expression back to the calling method.
d) The keyword __________ indicates that a method does not return a value.
e) Data can be added or removed only from the __________ of a stack.
f) Stacks are known as __________ data structures; the last item pushed (inserted) on the stack is the first item popped (removed) from the stack.
g) The three ways to return control from a called method to a caller are __________, __________ and __________.
h) An object of class __________ produces random numbers.
i) The program-execution stack contains the memory for local variables on each invocation of a method during a program’s execution. This data, stored as a portion of the program-execution stack, is known as the __________ or __________ of the method call.
j) If there are more method calls than can be stored on the program-execution stack, an error known as a(n) __________ occurs.
k) The __________ of a declaration is the portion of a program that can refer to the entity in the declaration by name.
l) It’s possible to have several methods with the same name that each operate on different types or numbers of arguments. This feature is called method __________.
m) The program-execution stack is also referred to as the __________ stack.
D.2 For the class Craps
in Fig. D.5, state the scope of each of the following entities:
a) the variable randomNumbers
.
b) the variable die1
.
c) the method rollDice
.
d) the method main
.
e) the variable sumOfDice
.
D.3 Write an application that tests whether the examples of the Math
class method calls shown in Fig. D.1 actually produce the indicated results.
D.4 Give the method header for each of the following methods:
a) Method hypotenuse
, which takes two double-precision, floating-point arguments side1
and side2
and returns a double-precision, floating-point result.
b) Method smallest
, which takes three integers x
, y
and z
and returns an integer.
c) Method instructions
, which does not take any arguments and does not return a value. [Note: Such methods are commonly used to display instructions to a user.]
d) Method intToFloat
, which takes integer argument number
and returns a float
.
D.5 Find the error in each of the following program segments. Explain how to correct the error.
a)
void g()
{
System.out.println( "Inside method g");
void h()
{
System.out.println( "Inside method h" );
}
}
b)
int sum( int x, int y )
{
int result;
result = x + y;
}
c)
void f( float a );
{
float a;
System.out.println( a );
}
D.6 Write a complete Java application to prompt the user for the double
radius of a sphere, and call method sphereVolume
to calculate and display the volume of the sphere. Use the following statement to calculate the volume:
double volume = ( 4.0 / 3.0 ) * Math.PI * Math.pow( radius, 3 )
a) method call.
b) local variable.
c) return
.
d) void
.
e) top.
f) last-in, first-out (LIFO).
g) return;
or return
expression;
or encountering the closing right brace of a method.
h) Random
.
i) activation record, stack frame.
j) stack overflow.
k) scope.
l) method overloading.
m) method call.
a) class body.
b) block that defines method rollDice
’s body.
c) class body.
d) class body.
e) block that defines method main
’s body.
D.3 The following solution demonstrates the Math
class methods in Fig. D.1:
1 // Exercise D.3: MathTest.java
2 // Testing the Math class methods.
3
4 public class MathTest
5 {
6 public static void main( String[] args )
7 {
8 System.out.printf( "Math.abs( 23.7 ) = %f
", Math.abs( 23.7 ) );
9 System.out.printf( "Math.abs( 0.0 ) = %f
", Math.abs( 0.0 ) );
10 System.out.printf( "Math.abs( -23.7 ) = %f
", Math.abs( -23.7 ) );
11 System.out.printf( "Math.ceil( 9.2 ) = %f
", Math.ceil( 9.2 ) );
12 System.out.printf( "Math.ceil( -9.8 ) = %f
", Math.ceil( -9.8 ) );
13 System.out.printf( "Math.cos( 0.0 ) = %f
", Math.cos( 0.0 ) );
14 System.out.printf( "Math.exp( 1.0 ) = %f
", Math.exp( 1.0 ) );
15 System.out.printf( "Math.exp( 2.0 ) = %f
", Math.exp( 2.0 ) );
16 System.out.printf( "Math.floor( 9.2 ) = %f
", Math.floor( 9.2 ) );
17 System.out.printf( "Math.floor( -9.8 ) = %f
",
18 Math.floor( -9.8 ) );
19 System.out.printf( "Math.log( Math.E ) = %f
",
20 Math.log( Math.E ) );
21 System.out.printf( "Math.log( Math.E * Math.E ) = %f
",
22 Math.log( Math.E * Math.E ) );
23 System.out.printf( "Math.max( 2.3, 12.7 ) = %f
",
24 Math.max( 2.3, 12.7 ) );
25 System.out.printf( "Math.max( -2.3, -12.7 ) = %f
",
26 Math.max( -2.3, -12.7 ) );
27 System.out.printf( "Math.min( 2.3, 12.7 ) = %f
",
28 Math.min( 2.3, 12.7 ) );
29 System.out.printf( "Math.min( -2.3, -12.7 ) = %f
",
30 Math.min( -2.3, -12.7 ) );
31 System.out.printf( "Math.pow( 2.0, 7.0 ) = %f
",
32 Math.pow( 2.0, 7.0 ) );
33 System.out.printf( "Math.pow( 9.0, 0.5 ) = %f
",
34 Math.pow( 9.0, 0.5 ) );
35 System.out.printf( "Math.sin( 0.0 ) = %f
", Math.sin( 0.0 ) );
36 System.out.printf( "Math.sqrt( 900.0 ) = %f
",
37 Math.sqrt( 900.0 ) );
38 System.out.printf( "Math.tan( 0.0 ) = %f
", Math.tan( 0.0 ) );
39 } // end main
40 } // end class MathTest
Math.abs( 23.7 ) = 23.700000
Math.abs( 0.0 ) = 0.000000
Math.abs( -23.7 ) = 23.700000
Math.ceil( 9.2 ) = 10.000000
Math.ceil( -9.8 ) = -9.000000
Math.cos( 0.0 ) = 1.000000
Math.exp( 1.0 ) = 2.718282
Math.exp( 2.0 ) = 7.389056
Math.floor( 9.2 ) = 9.000000
Math.floor( -9.8 ) = -10.000000
Math.log( Math.E ) = 1.000000
Math.log( Math.E * Math.E ) = 2.000000
Math.max( 2.3, 12.7 ) = 12.700000
Math.max( -2.3, -12.7 ) = -2.300000
Math.min( 2.3, 12.7 ) = 2.300000
Math.min( -2.3, -12.7 ) = -12.700000
Math.pow( 2.0, 7.0 ) = 128.000000
Math.pow( 9.0, 0.5 ) = 3.000000
Math.sin( 0.0 ) = 0.000000
Math.sqrt( 900.0 ) = 30.000000
Math.tan( 0.0 ) = 0.000000
a) double hypotenuse(
double side1,
double side2 )
b) int smallest(
int x,
int y,
int z )
c) void instructions()
d) float intToFloat(
int number )
a) Error: Method h
is declared within method g
.
Correction: Move the declaration of h
outside the declaration of g
.
b) Error: The method is supposed to return an integer, but does not.
Correction: Delete the variable result
, and place the statement
return x + y;
to the method, or add the following statement at the end of the method body:
return result;
c) Error: The semicolon after the right parenthesis of the parameter list is incorrect, and the parameter a
should not be redeclared in the method.
Correction: Delete the semicolon after the right parenthesis of the parameter list, and delete the declaration float a;
.
D.6 The following solution calculates the volume of a sphere, using the radius entered by the user:
1 // Exercise D.6: Sphere.java
2 // Calculate the volume of a sphere.
3 import java.util.Scanner;
4
5 public class Sphere
6 {
7 // obtain radius from user and display volume of sphere
8 public static void main( String[] args )
9 {
10 Scanner input = new Scanner( System.in );
11 System.out.print( "Enter radius of sphere: " );
12 double radius = input.nextDouble();
13 System.out.printf( "Volume is %f
", sphereVolume( radius ) );
14 } // end method determineSphereVolume
15
16 // calculate and return sphere volume
17 public static double sphereVolume( double radius )
18 {
19 double volume = ( 4.0 / 3.0 ) * Math.PI * Math.pow( radius, 3 );
20 return volume;
21 } // end method sphereVolume
22 } // end class Sphere
Enter radius of sphere: 4
Volume is 268.082573
a) x = Math.abs( 7.5 );
b) x = Math.floor( 7.5 );
c) x = Math.abs( 0.0 );
d) x = Math.ceil( 0.0 );
e) x = Math.abs( -6.4 );
f) x = Math.ceil( -6.4 );
g) x = Math.ceil( -Math.abs( -8 + Math.floor( -5.5 ) ) );
D.8 (Parking Charges) A parking garage charges a $2.00 minimum fee to park for up to three hours. The garage charges an additional $0.50 per hour for each hour or part thereof in excess of three hours. The maximum charge for any given 24-hour period is $10.00. Assume that no car parks for longer than 24 hours at a time. Write an application that calculates and displays the parking charges for each customer who parked in the garage yesterday. You should enter the hours parked for each customer. The program should display the charge for the current customer and should calculate and display the running total of yesterday’s receipts. It should use the method calculateCharges
to determine the charge for each customer.
D.9 (Rounding Numbers) Math.floor
can be used to round values to the nearest integer—e.g.,
y = Math.floor( x + 0.5 );
will round the number x
to the nearest integer and assign the result to y
. Write an application that reads double
values and uses the preceding statement to round each of the numbers to the nearest integer. For each number processed, display both the original number and the rounded number.
D.10 (Rounding Numbers) T
o round numbers to specific decimal places, use a statement like
y = Math.floor( x * 10 + 0.5 ) / 10;
which rounds x
to the tenths position (i.e., the first position to the right of the decimal point), or
y = Math.floor( x * 100 + 0.5 ) / 100;
which rounds x
to the hundredths position (i.e., the second position to the right of the decimal point). Write an application that defines four methods for rounding a number x
in various ways:
a) roundToInteger( number )
b) roundToTenths( number )
c) roundToHundredths( number )
d) roundToThousandths( number )
For each value read, your program should display the original value, the number rounded to the nearest integer, the number rounded to the nearest tenth, the number rounded to the nearest hundredth and the number rounded to the nearest thousandth.
D.11 Answer each of the following questions:
a) What does it mean to choose numbers “at random”?
b) Why is the nextInt
method of class Random
useful for simulating games of chance?
c) Why is it often necessary to scale or shift the values produced by a Random
object?
d) Why is computerized simulation of real-world situations a useful technique?
D.12 Write statements that assign random integers to the variable n in the following ranges:
a) 1 ≤ n ≤ 2.
b) 1 ≤ n ≤ 100.
c) 0 ≤ n ≤ 9.
d) 1000 ≤ n ≤ 1112.
e) —1 ≤ n ≤ 1.
f) —3 ≤ n ≤ 11.
D.13 Write statements that will display a random number from each of the following sets:
a) 2, 4, 6, 8, 10.
b) 3, 5, 7, 9, 11.
c) 6, 10, 14, 18, 22.
D.14 (Exponentiation) Write a method integerPower(base, exponent)
that returns the value of baseexponent
For example, integerPower(3, 4)
calculates 3
4
(or 3 * 3 * 3 * 3
). Assume that exponent
is a positive, nonzero integer and that base
is an integer. Use a for
or while
statement to control the calculation. Do not use any Math
class methods. Incorporate this method into an application that reads integer values for base
and exponent
and performs the calculation with the integerPower
method.
D.15 (Multiples) Write a method isMultiple
that determines, for a pair of integers, whether the second integer is a multiple of the first. The method should take two integer arguments and return true
if the second is a multiple of the first and false
otherwise. [Hint: Use the remainder operator.] Incorporate this method into an application that inputs a series of pairs of integers (one pair at a time) and determines whether the second value in each pair is a multiple of the first.
D.16 (Even or Odd) Write a method isEven
that uses the remainder operator (%
) to determine whether an integer is even. The method should take an integer argument and return true
if the integer is even and false
otherwise. Incorporate this method into an application that inputs a sequence of integers (one at a time) and determines whether each is even or odd.
D.17 (Circle Area) Write an application that prompts the user for the radius of a circle and uses a method called circleArea
to calculate the area of the circle.
D.18 (Temperature Conversions) Implement the following integer methods:
a) Method celsius
returns the Celsius equivalent of a Fahrenheit temperature, using the calculation
celsius = 5.0 / 9.0 * ( fahrenheit - 32 );
b) Method fahrenheit
returns the Fahrenheit equivalent of a Celsius temperature, using the calculation
fahrenheit = 9.0 / 5.0 * celsius + 32;
c) Use the methods from parts (a) and (b) to write an application that enables the user either to enter a Fahrenheit temperature and display the Celsius equivalent or to enter a Celsius temperature and display the Fahrenheit equivalent.
D.19 (Find the Minimum) Write a method minimum3
that returns the smallest of three floating-point numbers. Use the Math.min
method to implement minimum3
. Incorporate the method into an application that reads three values from the user, determines the smallest value and displays the result.
D.20 (Greatest Common Divisor) The greatest common divisor (GCD) of two integers is the largest integer that evenly divides each of the two numbers. Write a method gcd
that returns the greatest common divisor of two integers. [Hint: You might want to use Euclid’s algorithm. You can find information about it at en.wikipedia.org/wiki/Euclidean_algorithm
.] Incorporate the method into an application that reads two values from the user and displays the result.
D.21 (Quality Points) Write a method qualityPoints
that inputs a student’s average and returns 4
if it’s 90–100, 3
if 80–89, 2
if 70–79, 1
if 60–69 and 0
if lower than 60. Incorporate the method into an application that reads a value from the user and displays the result.
D.22 (Coin Tossing) Write an application that simulates coin tossing. Let the program toss a coin each time the user chooses the “Toss Coin
” menu option. Count the number of times each side of the coin appears. Display the results. The program should call a separate method flip
that takes no arguments and returns a value from a Coin enum
(HEADS
and TAILS
). [Note: If the program realistically simulates coin tossing, each side of the coin should appear approximately half the time.]
D.23 (Guess the Number) Write an application that plays “guess the number” as follows: Your program chooses the number to be guessed by selecting a random integer in the range 1 to 1000. The application displays the prompt Guess a number between 1 and 1000
. The player inputs a first guess. If the player’s guess is incorrect, your program should display "Too high. Try again."
or "Too low. Try again."
to help the player “zero in” on the correct answer. The program should prompt the user for the next guess. When the user enters the correct answer, display "Congratulations. You
guessed the number!"
, and allow the user to choose whether to play again. The guessing technique employed in this problem is similar to a binary search.
D.24 (Craps Game Modification) Modify the craps program of Fig. D.5 to allow wagering. Initialize variable bankBalance
to 1000 dollars. Prompt the player to enter a wager
. Check that wager
is less than or equal to bankBalance
, and if it’s not, have the user reenter wager
until a valid wager
is entered. Then, run one game of craps. If the player wins, increase bankBalance
by wager
and display the new bankBalance
. If the player loses, decrease bankBalance
by wager
, display the new bankBalance
, check whether bankBalance
has become zero and, if so, display the message "Sorry. You busted!"
As the game progresses, display various messages to create some “chatter,” such as "Oh, you're going for broke, huh?"
or "Aw c'mon, take a chance!"
or "You're up big. Now's the time to cash in your chips!"
. Implement the “chatter” as a separate method that randomly chooses the string to display.
D.25 (Computer-Assisted Instruction) The use of computers in education is referred to as computer-assisted instruction (CAI). Write a program that will help an elementary school student learn multiplication. Use a Random
object to produce two positive one-digit integers. The program should then prompt the user with a question, such as
How much is 6 times 7?
The student then inputs the answer. Next, the program checks the student’s answer. If it’s correct, display the message "Very good!"
and ask another multiplication question. If the answer is wrong, display the message "No. Please try again."
and let the student try the same question repeatedly until the student finally gets it right. A separate method should be used to generate each new question. This method should be called once when the application begins execution and each time the user answers the question correctly.
D.26 (Computer-Assisted Instruction: Reducing Student Fatigue) One problem in CAI environments is student fatigue. This can be reduced by varying the computer’s responses to hold the student’s attention. Modify the program of Exercise D.25 so that various comments are displayed for each answer as follows:
Possible responses to a correct answer:
Very good!
Excellent!
Nice work!
Keep up the good work!
Possible responses to an incorrect answer:
No. Please try again.
Wrong. Try once more.
Don't give up!
No. Keep trying.
Use random-number generation to choose a number from 1 to 4 that will be used to select one of the four appropriate responses to each correct or incorrect answer. Use a switch
statement to issue the responses.
D.27 (Computer-Assisted Instruction: Varying the Types of Problems) Modify the previous program to allow the user to pick a type of arithmetic problem to study. An option of 1
means addition problems only, 2
means subtraction problems only, 3
means multiplication problems only, 4
means division problems only and 5
means a random mixture of all these types.
3.133.124.21