System, but they may not be reproduced for publication



Yüklə 83 Mb.
Pdf görüntüsü
səhifə52/82
tarix19.04.2023
ölçüsü83 Mb.
#106251
1   ...   48   49   50   51   52   53   54   55   ...   82
Java A Beginner’s Guide, Eighth Edition ( PDFDrive )

 Chapter 11 Self Test
1.
How does Java’s multithreading capability enable you to write more efficient
programs?
2.
Multithreading is supported by the _________ class and the ________ interface.
3.
When creating a runnable object, why might you want to extend Thread rather than
implement Runnable?
4.
Show how to use join( ) to wait for a thread object called MyThrd to end.
5.
Show how to set a thread called MyThrd to three levels above normal priority.
6.
What is the effect of adding the synchronized keyword to a method?
7.
The wait( ) and notify( ) methods are used to perform
_______________________.
8.
Change the TickTock class so that it actually keeps time. That is, have each tick take
one half second, and each tock take one half second. Thus, each tick­tock will take one
second. (Don’t worry about the time it takes to switch tasks, etc.)


9.
Why can’t you use suspend( ), resume( ), and stop( ) for new programs?
10.
What method defined by Thread obtains the name of a thread?
11.
What does isAlive( ) return?
12. On your own, try adding synchronization to the Queue class developed in previous
chapters so that it is safe for multithreaded use.


Chapter 12
Enumerations, Autoboxing, Static Import, and
Annotations
Key Skills & Concepts

Understand enumeration fundamentals

Use the class­based features of enumerations

Apply the values( ) and valueof( ) methods to enumerations

Create enumerations that have constructors, instance variables, and
Playlists
History
Topics
Tutorials
Offers & Deals
Highlights
Settings
Support
Sign Out


T
methods

Employ the ordinal( ) and compareTo( ) methods that enumerations
inherit from Enum

Use Java’s type wrappers

Know the basics of autoboxing and auto­unboxing

Use autoboxing with methods

Understand how autoboxing works with expressions

Apply static import

Gain an overview of annotations
his chapter discusses enumerations, autoboxing, static import, and annotations.
Although none of these were part of the original definition of Java, each having been
added by JDK 5, they significantly enhanced the power and usability of the language. In
the case of enumerations and autoboxing, both addressed what was, at the time, long­
standing needs. Static import streamlined the use of static members. Annotations
expanded the kinds of information that can be embedded within a source file.
Collectively, these features offered a better way to solve common programming
problems. Frankly, today, it is difficult to imagine Java without them. They have
become that important. Also discussed in this chapter are Java’s type wrappers.
ENUMERATIONS
In its simplest form, an enumeration is a list of named constants that define a new data
type. An object of an enumeration type can hold only the values that are defined by the
list. Thus, an enumeration gives you a way to precisely define a new type of data that
has a fixed number of valid values.
Enumerations are common in everyday life. For example, an enumeration of the coins
used in the United States is penny, nickel, dime, quarter, half­dollar, and dollar. An
enumeration of the months in the year consists of the names January through
December. An enumeration of the days of the week is Sunday, Monday, Tuesday,
Wednesday, Thursday, Friday, and Saturday.
From a programming perspective, enumerations are useful whenever you need to


define a set of values that represent a collection of items. For example, you might use an
enumeration to represent a set of status codes, such as success, waiting, failed, and
retrying, which indicate the progress of some action. In the past, such values were
defined as final variables, but enumerations offer a more structured approach.
Enumeration Fundamentals
An enumeration is created using the enum keyword. For example, here is a simple
enumeration that lists various forms of transportation:
The identifiers CAR, TRUCK, and so on, are called enumeration constants. Each is
implicitly declared as a public, static member of Transport. Furthermore, the
enumeration constants’ type is the type of the enumeration in which the constants are
declared, which is Transport in this case. Thus, in the language of Java, these
constants are called self­typed, where “self” refers to the enclosing enumeration.
Once you have defined an enumeration, you can create a variable of that type. However,
even though enumerations define a class type, you do not instantiate an enum using
new. Instead, you declare and use an enumeration variable in much the same way that
you do one of the primitive types. For example, this declares tp as a variable of
enumeration type Transport:
Because tp is of type Transport, the only values that it can be assigned are those
defined by the enumeration. For example, this assigns tp the value AIRPLANE:
Notice that the symbol AIRPLANE is qualified by Transport.
Two enumeration constants can be compared for equality by using the = = relational
operator. For example, this statement compares the value in tp with the TRAIN
constant:


An enumeration value can also be used to control a switch statement. Of course, all of
the case statements must use constants from the same enum as that used by the
switch expression. For example, this switch is perfectly valid:
Notice that in the case statements, the names of the enumeration constants are used
without being qualified by their enumeration type name. That is, TRUCK, not
Transport.TRUCK, is used. This is because the type of the enumeration in the
switch expression has already implicitly specified the enum type of the case
constants. There is no need to qualify the constants in the case statements with their
enum type name. In fact, attempting to do so will cause a compilation error.
When an enumeration constant is displayed, such as in a println( ) statement, its
name is output. For example, given this statement:
the name BOAT is displayed.
The following program puts together all of the pieces and demonstrates the Transport
enumeration:


The output from the program is shown here:
Before moving on, it’s necessary to make one stylistic point. The constants in
Transport use uppercase. (Thus, CAR, not car, is used.) However, the use of


uppercase is not required. In other words, there is no rule that requires enumeration
constants to be in uppercase. Because enumerations often replace final variables,
which have traditionally used uppercase, some programmers believe that uppercasing
enumeration constants is also appropriate. There are, of course, other viewpoints and
styles. The examples in this book will use uppercase for enumeration constants, for
consistency.
JAVA ENUMERATIONS ARE CLASS TYPES
Although the preceding examples show the mechanics of creating and using an
enumeration, they don’t show all of its capabilities. Unlike the way enumerations are
implemented in some other languages, Java implements enumerations as class types.
Although you don’t instantiate an enum using new, it otherwise acts much like other
classes. The fact that enum defines a class enables the Java enumeration to have
powers that enumerations in some other languages do not. For example, you can give it
constructors, add instance variables and methods, and even implement interfaces.
THE VALUES( ) AND VALUEOF( ) METHODS
All enumerations automatically have two predefined methods: values( ) and valueOf(
). Their general forms are shown here:
public static enum­type[ ] values( )
public static enum­type valueOf(String str)
The values( ) method returns an array that contains a list of the enumeration
constants. The valueOf( ) method returns the enumeration constant whose value
corresponds to the string passed in str. In both cases, enum­type is the type of the
enumeration. For example, in the case of the Transport enumeration shown earlier,
the return type of Transport.valueOf("TRAIN") is Transport. The value returned
is TRAIN. The following program demonstrates the values( ) and valueOf( )
methods:


The output from the program is shown here:
Notice that this program uses a for­each style for loop to cycle through the array of
constants obtained by calling values( ). For the sake of illustration, the variable
allTransports was created and assigned a reference to the enumeration array.
However, this step is not necessary because the for could have been written as shown
here, eliminating the need for the allTransports variable:
Now, notice how the value corresponding to the name AIRPLANE was obtained by
calling valueOf( ):


As explained, valueOf( ) returns the enumeration value associated with the name of
the constant represented as a string.
CONSTRUCTORS, METHODS, INSTANCE
VARIABLES, AND ENUMERATIONS
It is important to understand that each enumeration constant is an object of its
enumeration type. Thus, an enumeration can define constructors, add methods, and
have instance variables. When you define a constructor for an enum, the constructor is
called when each enumeration constant is created. Each enumeration constant can call
any method defined by the enumeration. Each enumeration constant has its own copy
of any instance variables defined by the enumeration. The following version of
Transport illustrates the use of a constructor, an instance variable, and a method. It
gives each type of transportation a typical speed.
The output is shown here:


This version of Transport adds three things. The first is the instance variable speed,
which is used to hold the speed of each kind of transport. The second is the Transport
constructor, which is passed the speed of a transport. The third is the method
getSpeed( ), which returns the value of speed.
When the variable tp is declared in main( ), the constructor for Transport is called
once for each constant that is specified. Notice how the arguments to the constructor
are specified, by putting them inside parentheses, after each constant, as shown here:
These values are passed to the s parameter of Transport( ), which then assigns this
value to speed. There is something else to notice about the list of enumeration
constants: it is terminated by a semicolon. That is, the last constant, BOAT, is followed
by a semicolon. When an enumeration contains other members, the enumeration list
must end in a semicolon.
Because each enumeration constant has its own copy of speed, you can obtain the
speed of a specified type of transport by calling getSpeed( ). For example, in main( )
the speed of an airplane is obtained by the following call:
The speed of each transport is obtained by cycling through the enumeration using a for
loop. Because there is a copy of speed for each enumeration constant, the value
associated with one constant is separate and distinct from the value associated with
another constant. This is a powerful concept, which is available only when
enumerations are implemented as classes, as Java does.
Although the preceding example contains only one constructor, an enum can offer two
or more overloaded forms, just as can any other class.


Ask the Expert
Q
: Since enumerations have been added to Java, should I avoid the use
of final variables? In other words, have enumerations rendered final
variables obsolete?
A
: No. Enumerations are appropriate when you are working with lists of items
that must be represented by identifiers. A final variable is appropriate when you
have a constant value, such as an array size, that will be used in many places. Thus,
each has its own use. The advantage of enumerations is that final variables don’t
have to be pressed into service for a job for which they are not ideally suited.
Two Important Restrictions
There are two restrictions that apply to enumerations. First, an enumeration can’t
inherit another class. Second, an enum cannot be a superclass. This means that an
enum can’t be extended. Otherwise, enum acts much like any other class type. The
key is to remember that each of the enumeration constants is an object of the class in
which it is defined.
ENUMERATIONS INHERIT ENUM
Although you can’t inherit a superclass when declaring an enum, all enumerations
automatically inherit one: java.lang.Enum. This class defines several methods that
are available for use by all enumerations. Most often, you won’t need to use these
methods, but there are two that you may occasionally employ: ordinal( ) and
compareTo( ).
The ordinal( ) method obtains a value that indicates an enumeration constant’s
position in the list of constants. This is called its ordinal value. The ordinal( ) method
is shown here:
final int ordinal( )
It returns the ordinal value of the invoking constant. Ordinal values begin at zero. Thus,
in the Transport enumeration, CAR has an ordinal value of zero, TRUCK has an
ordinal value of 1, AIRPLANE has an ordinal value of 2, and so on.


You can compare the ordinal value of two constants of the same enumeration by using
the compareTo( ) method. It has this general form:
final int compareTo(enum­type e)
Here, enum­type is the type of the enumeration and e is the constant being compared
to the invoking constant. Remember, both the invoking constant and e must be of the
same enumeration. If the invoking constant has an ordinal value less than e’s, then
compareTo( ) returns a negative value. If the two ordinal values are the same, then
zero is returned. If the invoking constant has an ordinal value greater than e’s, then a
positive value is returned.
The following program demonstrates ordinal( ) and compareTo( ):
The output from the program is shown here:


Try This 12­1
A Computer­Controlled Traffic Light
Enumerations are particularly useful when your program needs a set of constants, but
the actual values of the constants are arbitrary, as long as all differ. This type of
situation comes up quite often when programming. One common instance involves
handling the states in which some device can exist. For example, imagine that you are
writing a program that controls a traffic light. Your traffic light code must
automatically cycle through the light’s three states: green, yellow, and red. It also must
enable other code to know the current color of the light and let the color of the light be
set to a known initial value. This means that the three states must be represented in
some way. Although it would be possible to represent these three states by integer
values (for example, the values 1, 2, and 3) or by strings (such as "red", "green", and
"yellow"), an enumeration offers a much better approach. Using an enumeration
results in code that is more efficient than if strings represented the states and more
structured than if integers represented the states.
In this project, you will create a simulation of an automated traffic light, as just
described. This project not only demonstrates an enumeration in action, it also shows
another example of multithreading and synchronization.
1. Create a file called TrafficLightDemo.java.
2. Begin by defining an enumeration called TrafficLightColor that represents the
three states of the light, as shown here:


Whenever the color of the light is needed, its enumeration value is used.
3. Next, begin defining TrafficLightSimulator, as shown next.
TrafficLightSimulator is the class that encapsulates the traffic light simulation.
Notice that TrafficLightSimulator implements Runnable. This is necessary
because a separate thread is used to run each traffic light. This thread will cycle
through the colors. Two constructors are created. The first lets you specify the initial
light color. The second defaults to red.
Now look at the instance variables. A reference to the traffic light thread is stored in
thrd. The current traffic light color is stored in tlc. The stop variable is used to stop
the simulation. It is initially set to false. The light will run until this variable is set to
true. The changed variable is true when the light has changed.
4. Next, add the run( ) method, shown here, which begins running the traffic light:


This method cycles the light through the colors. First, it sleeps an appropriate amount
of time, based on the current color. Then, it calls changeColor( ) to change to the
next color in the sequence.
5. Now, add the changeColor( ) method, as shown here:


The switch statement examines the color currently stored in tlc and then assigns the
next color in the sequence. Notice that this method is synchronized. This is necessary
because it calls notify( ) to signal that a color change has taken place. (Recall that
notify( ) can be called only from a synchronized context.)
6. The next method is waitForChange( ), which waits until the color of the light is
changed.
This method simply calls wait( ). This call won’t return until changeColor( )
executes a call to notify( ). Thus, waitForChange( ) won’t return until the color has
changed.
7. Finally, add the methods getColor( ), which returns the current light color, and
cancel( ), which stops the traffic light thread by setting stop to true. These methods
are shown here:
8. Here is all the code assembled into a complete program that demonstrates the traffic
light:



The following output is produced. As you can see, the traffic light cycles through the


colors in order of green, yellow, and red:
In the program, notice how the use of the enumeration simplifies and adds structure to
the code that needs to know the state of the traffic light. Because the light can have only
three states (red, green, or yellow), the use of an enumeration ensures that only these
values are valid, thus preventing accidental misuse.
9. It is possible to improve the preceding program by taking advantage of the class
capabilities of an enumeration. For example, by adding a constructor, instance
variable, and method to TrafficLightColor, you can substantially improve the
preceding programming. This improvement is left as an exercise. See Self Test,
question 4.
AUTOBOXING
Beginning with JDK 5, Java has included two very helpful features: autoboxing and

Yüklə 83 Mb.

Dostları ilə paylaş:
1   ...   48   49   50   51   52   53   54   55   ...   82




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə