Chapter 9
In This Chapter
Defining constructors
Using constructors in subclasses
Using Java’s default constructor features
Constructing a simple GUI
Ms. Jennie Burd
121 Schoolhouse Lane
Anywhere, Kansas
Dear Ms. Burd,
In response to your letter of June 21, I believe I can say with complete assurance that objects are not created spontaneously from nothing. Although I’ve never actually seen an object being created (and no one else in this office can claim to have seen an object in its moment of creation), I have every confidence that some process or other is responsible for the building of these interesting and useful thingamajigs. We here at ClassesAndObjects.com support the unanimous opinions of both the scientific community and the private sector on matters of this nature. Furthermore, we agree with the recent finding of a Blue Ribbon Presidential Panel, which concludes beyond any doubt that spontaneous object creation would impede the present economic outlook.
Please be assured that I have taken all steps necessary to ensure the safety and well-being of you, our loyal customer. If you have any further questions, please do not hesitate to contact our complaint department. The department’s manager is Mr. Blake Wholl. You can contact him by visiting our company’s website.
Once again, let me thank you for your concern, and I hope you continue to patronize ClassesAndObjects.com.
Yours truly,
Mr. Scott Brickenchicker
The one who couldn’t get on the elevator in Chapter 4
Here’s a statement that creates an object:
Account myAccount = new Account();
I know this works — I got it from one of my own examples in Chapter 7. Anyway, in Chapter 7, I say, “when the computer executes new Account()
, you’re creating an object by calling the Account
class’s constructor.” What does this mean?
Well, when you ask the computer to create a new object, the computer responds by performing certain actions. For starters, the computer finds a place in its memory to store information about the new object. If the object has fields, the fields should eventually have meaningful values.
So one question is, when you ask the computer to create a new object, can you control what’s placed in the object’s fields? And what if you’re interested in doing more than filling fields? Perhaps, when the computer creates a new object, you have a whole list of jobs for the computer to carry out. For instance, when the computer creates a new window object, you want the computer to realign the sizes of all the buttons in that window.
Creating a new object can involve all kinds of tasks, so in this chapter, you create constructors. A constructor tells the computer to perform a new object’s startup tasks.
“Good morning, and welcome to Object News. The local temperature in your area is a pleasant 73 degrees Fahrenheit.”
Each temperature consists of two things: a number and a temperature scale. A number is just a double
value, such as 32.0 or 70.52. But what's a temperature scale? Is it a string of characters, like "Fahrenheit"
or "Celsius"
? Not really, because some strings aren't temperature scales. There's no "Quelploof"
temperature scale, and a program that can display the temperature “73 degrees Quelploof” is a bad program. So how can you limit the temperature scales to the small number of scales that people use? One way to do it is with Java's enum
type.
Java provides lots of ways for you to group things together. In Chapter 11, you group things together to form an array. And in Chapter 12, you group things together to form a collection. In this chapter, you group things into an enum
type. (Of course, you can’t group anything unless you can pronounce enum
. The word enum is pronounced ee-noom, like the first two syllables of the word enumeration.)
Creating a complicated enum
type isn’t easy, but to create a simple enum
type, just write a bunch of words inside a pair of curly braces. Listing 9-1 defines an enum
type. The name of the enum
type is TempScale
.
Listing 9-1: The TempScale enum Type
public enum TempScale {
CELSIUS, FAHRENHEIT, KELVIN, RANKINE,
NEWTON, DELISLE, RÉAUMUR, RØMER, LEIDEN
};
When you define an enum
type, two important things happen:
Just as 13
and 151
are int
values, CELSIUS
and FAHRENHEIT
are TempScale
values.
In Listing 9-2, I declare the fields number
and scale
. Just as double number
declares a number
variable is of type double
, TempScale scale
declares variable scale
to be of type TempScale
.
Being of type TempScale
means that you can have values CELSIUS
, FAHRENHEIT
, KELVIN
, and so on. So in Listing 9-2, I can give the scale
variable the value FAHRENHEIT
(or TempScale.FAHRENHEIT
, to be more precise).
Each temperature consists of two things: a number and a temperature scale. The code in Listing 9-2 makes this fact abundantly clear.
Listing 9-2: The Temperature Class
public class Temperature {
private double number;
private TempScale scale;
public Temperature() {
number = 0.0;
scale = TempScale.FAHRENHEIT;
}
public Temperature(double number) {
this.number = number;
scale = TempScale.FAHRENHEIT;
}
public Temperature(TempScale scale) {
number = 0.0;
this.scale = scale;
}
public Temperature(double number, TempScale scale) {
this.number = number;
this.scale = scale;
}
public void setNumber(double number) {
this.number = number;
}
public double getNumber() {
return number;
}
public void setScale(TempScale scale) {
this.scale = scale;
}
public TempScale getScale() {
return scale;
}
}
The code in Listing 9-2 has the usual setter and getter methods (accessor methods for the number
and scale
fields).
On top of all that, Listing 9-2 has four other method-like looking things. Each of these method-like things has the name Temperature
, which happens to be the same as the name of the class. None of these Temperature
method-like things has a return
type of any kind — not even void
, which is the cop-out return
type.
Each of these method-like things is called a constructor. A constructor is like a method, except that a constructor has a very special purpose — creating new objects.
You can omit the word public
in the first lines of Listings 2-9 and 1-4. If you omit public
, other Java programs might not be able to use the features defined in your TempScale
enum
and in your Temperature
class. (Don't worry about the programs in this chapter. With or without the word public
, all the programs in this chapter can use the code in Listings 2-9 and 1-4. To find out which Java programs can and cannot use non-public classes, see Chapter 14.) If you do use the word public
in the first line of Listing 9-1, Listing 9-1 must be in a file named TempScale.java
, starting with a capital letter T
. And if you do use the word public
in the first line of Listing 9-2, Listing 9-2 must be in a file named Temperature.java
, starting with a capital letter T
. (For an introduction to public
classes, see Chapter 7.)
Listing 9-3 gives form to some of the ideas that I describe in the preceding section. In Listing 9-3, you call the constructors that are declared back in Listing 9-2. Figure 9-1 shows what happens when you run all this code.
Listing 9-3: Using the Temperature Class
import static java.lang.System.out;
public class UseTemperature {
public static void main(String args[]) {
final String format = "%5.2f degrees %s
";
Temperature temp = new Temperature();
temp.setNumber(70.0);
temp.setScale(TempScale.FAHRENHEIT);
out.printf(format, temp.getNumber(),
temp.getScale());
temp = new Temperature(32.0);
out.printf(format, temp.getNumber(),
temp.getScale());
temp = new Temperature(TempScale.CELSIUS);
out.printf(format, temp.getNumber(),
temp.getScale());
temp = new Temperature(2.73, TempScale.KELVIN);
out.printf(format, temp.getNumber(),
temp.getScale());
}
}
In Listing 9-3, each statement of the kind
temp = new Temperature(blah,blah,blah);
calls one of the constructors from Listing 9-2. So, by the time the code in Listing 9-3 is done running, it creates four instances of the Temperature
class. Each instance is created by calling a different constructor from Listing 9-2.
In Listing 9-3, the last of the four constructor calls has two parameters — 2.73
and TempScale.KELVIN
. This isn't particular to constructor calls. A method call or a constructor call can have a bunch of parameters. You separate one parameter from another with a comma. Another name for “a bunch of parameters” is a parameter list.
The only rule you must follow is to match the parameters in the call with the parameters in the declaration. For example, in Listing 9-3, the fourth and last constructor call
new Temperature(2.73, TempScale.KELVIN)
has two parameters — the first of type double
, and the second of type TempScale
. Java approves of this constructor call because Listing 9-2 contains a matching declaration. That is, the header
public Temperature(double number, TempScale scale)
has two parameters — the first of type double
, and the second of type TempScale
. If a Temperature constructor call in Listing 9-3 had no matching declaration in Listing 9-2, then Listing 9-3 would crash and burn. (To state things more politely, Java would display errors when you tried to compile the code in Listing 9-3.)
By the way, this business about multiple parameters isn't new. Back in Chapter 6, I write keyboard.findWithinHorizon(".",0).charAt(0)
. In that line, the method call findWithinHorizon(".",0)
has two parameters — a string and an int
value. Lucky for me, the Java API has a method declaration for findWithinHorizon
— a declaration whose first parameter is a string, and whose second parameter is an int
value.
When the computer executes one of the new Temperature
statements in Listing 9-3, the computer has to decide which of the constructors in Listing 9-2 to use. The computer decides by looking at the parameter list — the stuff in parentheses after the words new Temperature
. For instance, when the computer executes
temp = new Temperature(32.0);
from Listing 9-3, the computer says to itself, “The number 32.0 in parentheses is a double
value. One of the Temperature
constructors in Listing 9-2 has just one parameter with type double
. The constructor’s header looks like this:
public Temperature(double number)
“So, I guess I’ll execute the statements inside that particular constructor.” The computer goes on to execute the following statements:
this.number = number;
scale = TempScale.FAHRENHEIT;
As a result, you get a brand-new object whose number
field has the value 32.0
and whose scale
field has the value TempScale.FAHRENHEIT
.
In the two lines of code, you have two statements that set values for the fields number
and scale
. Take a look at the second of these statements, which is a bit easier to understand. The second statement sets the new object’s scale
field to TempScale.FAHRENHEIT
. You see, the constructor’s parameter list is (double number)
, and that list doesn’t include a scale
value. So whoever programmed this code had to make a decision about what value to use for the scale
field. The programmer could have chosen FAHRENHEIT
or CELSIUS
, but she could also have chosen KELVIN
, RANKINE
, or any of the other obscure scales named in Listing 9-1. (This programmer happens to live in New Jersey, in the United States, where people commonly use the old Fahrenheit temperature scale.)
Marching back to the first of the two statements, this first statement assigns a value to the new object’s number
field. The statement uses a cute trick that you can see in many constructors (and in other methods that assign values to objects’ fields). To understand the trick, take a look at Listing 9-4. The listing shows you two ways that I could have written the same constructor code.
Listing 9-4: Two Ways to Accomplish the Same Thing
//Use this constructor …
public Temperature(double whatever) {
number = whatever;
scale = TempScale.FAHRENHEIT;
}
//… or use this constructor …
public Temperature(double number) {
this.number = number;
scale = TempScale.FAHRENHEIT;
}
//… but don't put both constructors in your code.
Listing 9-4 has two constructors in it. In the first constructor, I use two different names — number
and whatever
. In the second constructor, I don’t need two names. Instead of making up a new name for the constructor’s parameter, I reuse an existing name by writing this.number
.
So here’s what’s going on in Listing 9-2:
this.number = number
, the name this.number refers to the new object’s number
field — the field that’s declared near the very top of Listing 9-2. (See Figure 9-2.)
In the statement this.number = number
, number (on its own, without this
) refers to the constructor’s parameter. (Again, see Figure 9-2.)
In general, this.someName
refers to a field belonging to the object that contains the code. In contrast, plain old someName
refers to the closest place where someName
happens to be declared. In the statement this.number = number
(Listing 9-2), that closest place happens to be the Temperature
constructor’s parameter list.
Chapter 7 introduces the printf
method and explains that each printf
call starts with a format string. The format string describes the way the other parameters are to be displayed.
In previous examples, this format string is always a quoted literal. For instance, the first printf
call in Listing 7-7 is
out.printf("$%4.2f ", myInterest);
In Listing 9-3, I break with tradition and begin the printf
call with a variable that I name format.
out.printf(format, temp.getNumber(), temp.getScale());
That’s okay as long as my format
variable is of type String
. And indeed, in Listing 9-3, the first variable declaration is
final String format = "%5.2f degrees %s ";
In this declaration of the format
variable, take special note of the word final
. This Java keyword indicates that the value of format
can’t be changed. If I add another assignment statement to Listing 9-3
format = "%6.2f (%s) ";
then the compiler barks back at me with a cannot assign a value to final variable
message.
When I write the code in Listing 9-3, the use of the final
keyword isn’t absolutely necessary. But the final
keyword provides some extra protection. When I initialize format
to "%5.2f degrees %s
"
, I intend to use this same format
just as it is, over and over again. I know darn well that I don’t intend to change the format
variable’s value. Of course, in a 10,000-line program, I can become confused and try to assign a new value to format
somewhere deep down in the code. So to prevent me from accidentally changing the format string, I declare the format
variable to be final. It’s just good, safe programming practice.
In Chapter 8, I make a big fuss over the notion of subclasses. That’s the right thing to do. Subclasses make code reusable, and reusable code is good code. With that in mind, it’s time to create a subclass of the Temperature
class (which I develop in this chapter’s first section).
After perusing the code in Listing 9-3, you decide that the responsibility for displaying temperatures has been seriously misplaced. Listing 9-3 has several tedious repetitions of the lines to print temperature values. A 1970s programmer would tell you to collect those lines into one place and turn them into a method. (The 1970s programmer wouldn’t have used the word method, but that’s not important right now.) Collecting lines into methods is fine, but with today’s object-oriented programming methodology, you think in broader terms. Why not get each temperature
object to take responsibility for displaying itself? After all, if you develop a display
method, you probably want to share the method with other people who use temperatures. So put the method right inside the declaration of a temperature
object. That way, anyone who uses the code for temperatures has easy access to your display
method.
Now replay the tape from Chapter 8. “Blah, blah, blah … don’t want to modify existing code … blah, blah, blah … too costly to start again from scratch … blah, blah, blah … extend existing functionality.” It all adds up to one thing:
Don’t abuse it. Instead, reuse it.
So you decide to create a subclass of the Temperature
class — the class defined in Listing 9-2. Your new subclass complements the Temperature
class’s functionality by having methods to display values in a nice, uniform fashion. The new class, TemperatureNice
, is shown in Listing 9-5.
Listing 9-5: The TemperatureNice Class
import static java.lang.System.out;
public class TemperatureNice extends Temperature {
public TemperatureNice() {
super();
}
public TemperatureNice(double number) {
super(number);
}
public TemperatureNice(TempScale scale) {
super(scale);
}
public TemperatureNice(double number, TempScale scale)
{
super(number, scale);
}
public void display() {
out.printf("%5.2f degrees %s
",
getNumber(), getScale());
}
}
In the display
method of Listing 9-5, notice the calls to the Temperature
class’s getNumber
and getScale
methods. Why do I do this? Well, inside the TemperatureNice
class’s code, any direct references to the number
and scale
fields would generate error messages. It’s true that every TemperatureNice
object has its own number
and scale
fields. (After all, TemperatureNice
is a subclass of the Temperature
class, and the code for the Temperature
class defines the number
and scale
fields.) But because number
and scale
are declared to be private inside the Temperature
class, only code that’s right inside the Temperature
class can directly use these fields.
By far, the biggest news in Listing 9-5 is the way the code declares constructors. The TemperatureNice
class has four of its own constructors. If you’ve gotten in gear thinking about subclass inheritance, you may wonder why these constructor declarations are necessary. Doesn’t TemperatureNice
inherit the parent Temperature
class’s constructors? No, subclasses don’t inherit constructors.
That’s right. Subclasses don’t inherit constructors. In one oddball case, a constructor may look like it’s being inherited, but that oddball situation is a fluke, not the norm. In general, when you define a subclass, you declare new constructors to go with the subclass.
I describe the oddball case (in which a constructor looks like it’s being inherited) later in this chapter, in the section “The default constructor.”
So the code in Listing 9-5 has four constructors. Each constructor has the name TemperatureNice
, and each constructor has its own uniquely identifiable parameter list. That’s the boring part. The interesting part is that each constructor makes a call to something named super
, which is a Java keyword.
In Listing 9-5, super
stands for a constructor in the parent class.
super()
in Listing 9-5 calls the parameterless Temperature()
constructor that’s in Listing 9-2. That parameterless constructor assigns 0.0
to the number
field and TempScale.FAHRENHEIT
to the scale
field.super(number, scale)
in Listing 9-5 calls the constructor Temperature(double number, TempScale scale)
that’s in Listing 9-2. In turn, the constructor assigns values to the number
and scale
fields.super(number)
and super(scale)
in Listing 9-5 call constructors from Listing 9-2.The computer decides which of the Temperature
class’s constructors is being called by looking at the parameter list after the word super
. For instance, when the computer executes
super(number, scale);
from Listing 9-5, the computer says to itself, “The number
and scale
fields in parentheses have types double
and TempScale
. But only one of the Temperature
constructors in Listing 9-2 has two parameters with types double
and TempScale
. The constructor’s header looks like this:
public Temperature(double number, TempScale scale)
“So, I guess I’ll execute the statements inside that particular constructor.”
In Listing 9-5, I define what it means to be in the TemperatureNice
class. Now it’s time to put this TemperatureNice
class to good use. Listing 9-6 has code that uses TemperatureNice
.
Listing 9-6: Using the TemperatureNice Class
public class UseTemperatureNice {
public static void main(String args[]) {
TemperatureNice temp = new TemperatureNice();
temp.setNumber(70.0);
temp.setScale(TempScale.FAHRENHEIT);
temp.display();
temp = new TemperatureNice(32.0);
temp.display();
temp = new TemperatureNice(TempScale.CELSIUS);
temp.display();
temp = new TemperatureNice(2.73,
TempScale.KELVIN);
temp.display();
}
}
The code in Listing 9-6 is very much like its cousin code in Listing 9-3. The big differences are as follows:
TemperatureNice
class. That is, Listing 9-6 calls constructors from the TemperatureNice
class, not the Temperature
class.display
method in the TemperatureNice
class. So the code in Listing 9-6 is much tidier than its counterpart in Listing 9-3.A run of Listing 9-6 looks exactly like a run of the code in Listing 9-3 — it just gets to the finish line in far more elegant fashion. (The run is shown previously in Figure 9-1.)
The main message in the previous section is that subclasses don’t inherit constructors. So what gives with all the listings back in Chapter 8? In Listing 8-6, a statement says
FullTimeEmployee ftEmployee = new FullTimeEmployee();
But, here’s the problem: The code defining FullTimeEmployee
(Listing 8-3) doesn’t seem to have any constructors declared inside it. So, in Listing 8-6, how can you possibly call the FullTimeEmployee
constructor?
Here’s what’s going on. When you create a subclass and don’t put any explicit constructor declarations in your code, Java creates one constructor for you. It’s called a default constructor. If you’re creating the public FullTimeEmployee
subclass, the default constructor looks like the one in Listing 9-7.
Listing 9-7: A Default Constructor
public FullTimeEmployee() {
super();
}
The constructor in Listing 9-7 takes no parameters, and its one statement calls the constructor of whatever class you’re extending. (Woe be to you if the class that you’re extending doesn’t have a parameterless constructor.)
You’ve just read about default constructors, but watch out! Notice one thing that this talk about default constructors doesn’t say: It doesn’t say that you always get a default constructor. In particular, if you create a subclass and define any constructors yourself, Java doesn’t add a default constructor for the subclass (and the subclass doesn’t inherit any constructors, either).
So how can this trip you up? Listing 9-8 has a copy of the code from Listing 8-3, but with one constructor added to it. Take a look at this modified version of the FullTimeEmployee
code.
Listing 9-8: Look, I Have a Constructor!
public class FullTimeEmployee extends Employee {
private double weeklySalary;
private double benefitDeduction;
public FullTimeEmployee(double weeklySalary) {
this.weeklySalary = weeklySalary;
}
public void setWeeklySalary(double weeklySalaryIn) {
weeklySalary = weeklySalaryIn;
}
public double getWeeklySalary() {
return weeklySalary;
}
public void setBenefitDeduction(double benefitDedIn) {
benefitDeduction = benefitDedIn;
}
public double getBenefitDeduction() {
return benefitDeduction;
}
public double findPaymentAmount() {
return weeklySalary - benefitDeduction;
}
}
If you use the FullTimeEmployee
code in Listing 9-8, a line like the following doesn’t work:
FullTimeEmployee ftEmployee = new FullTimeEmployee();
It doesn’t work because, having declared a FullTimeEmployee
constructor that takes one double
parameter, you no longer get a default parameterless constructor for free.
So what do you do about this? If you declare any constructors, declare all the constructors that you’re possibly going to need. Take the constructor in Listing 9-7 and add it to the code in Listing 9-8. Then the call new FullTimeEmployee()
starts working again.
Here’s a quote from someplace near the start of this chapter: “And what if you’re interested in doing more than filling fields? Perhaps, when the computer creates a new object, you have a whole list of jobs for the computer to carry out.” Okay, what if?
This section’s example has a constructor that does more than just assign values to fields. The example is in Listings 2-9 and 9-4. The result of running the example’s code is shown in Figure 9-3.
Listing 9-9: Defining a Frame
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JButton;
@SuppressWarnings("serial")
public class SimpleFrame extends JFrame {
public SimpleFrame() {
setTitle("Don't click the button!");
setLayout(new FlowLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
add(new JButton("Panic"));
setSize(300, 100);
setVisible(true);
}
}
Listing 9-10: Displaying a Frame
public class ShowAFrame {
public static void main(String args[]) {
new SimpleFrame();
}
}
The code in Listing 9-9 is made up mostly of calls to Java API (Application Programming Interface) methods. What this means to you is that the code contains lots of names that are probably unfamiliar to you. When I was first becoming acquainted with Java, I foolishly believed that knowing Java meant knowing all these names. Quite the contrary: These names are just carry-on baggage. The real Java is the way the language implements object-oriented concepts.
Anyway, Listing 9-10’s main method has only one statement: a call to the constructor in the SimpleFrame
class. Notice how the object that this call creates isn’t even assigned to a variable. That’s okay because the code doesn’t need to refer to the object anywhere else.
Up in the SimpleFrame
class is only one constructor declaration. Far from just setting variables’ values, this constructor calls method after method from the Java API.
All the methods called in the SimpleFrame
class’s constructor come from the parent class, JFrame
. The JFrame
class lives in the javax.swing
package. This package and another package, java.awt
, have classes that help you put windows, images, drawings, and other gizmos on a computer screen. (In the java.awt
package, the letters awt stand for abstract windowing toolkit.)
For a little gossip about the notion of a Java package, see the sidebar entitled “Packages and import declarations.” For lots of gossip about the notion of a Java package, see Chapter 14.
Looking at Figure 9-3, you can probably tell that an instance of the SimpleFrame
class doesn’t do much. The frame has only one button, and when you click the button, nothing happens. I made the frame this way to keep the example from becoming too complicated. Even so, the code in Listing 9-9 uses several API classes and methods. The setTitle
, setLayout
, setDefaultCloseOperation
, add
, setSize
, and setVisible
methods all belong to the javax.swing.JFrame
class. Here’s a list of names used in the code:
setTitle
: Calling setTitle
puts words in the frame’s title bar. (The new SimpleFrame
object is calling its own setTitle
method.)FlowLayout
: An instance of the FlowLayout
class positions objects on the frame in centered, typewriter fashion. Because the frame in Figure 9-3 has only one button on it, that button is centered near the top of the frame. If the frame had eight buttons, five of them may be lined up in a row across the top of the frame and the remaining three would be centered along a second row.setLayout
: Calling setLayout
puts the new FlowLayout
object in charge of arranging components, such as buttons, on the frame. (The new SimpleFrame
object is calling its own setLayout
method.)setDefaultCloseOperation
: Calling setDefaultCloseOperation
tells Java what to do when you click the little × in the frame’s upper-right corner. Without this method call, the frame itself disappears, but the Java Virtual Machine (JVM) keeps running. If you use Eclipse, you have to halt the JVM by clicking the red square near the top of the Console view. (See Figure 9-4.)
Calling setDefaultCloseOperation(EXIT_ON_CLOSE)
tells Java to shut itself down when you click the × in the frame’s upper-right corner. The alternatives to EXIT_ON_CLOSE
are HIDE_ON_CLOSE
, DISPOSE_ON_CLOSE
, and my personal favorite, DO_NOTHING_ON_CLOSE
.
JButton
: The JButton
class lives in the javax.swing
package. One of the class’s constructors takes a String
instance (such as "Panic"
) for its parameter. Calling this constructor makes that String
instance into the label on the face of the new button.add
: The new SimpleFrame
object calls its add
method. Calling the add
method places the button on the object’s surface (in this case, the surface of the frame).setSize
: The frame becomes 300 pixels wide and 100 pixels tall. (In the javax.swing
package, whenever you specify two dimension numbers, the width number always comes before the height number.)setVisible
: When it’s first created, a new frame is invisible. But when the new frame calls setVisible(true)
, the frame appears on your computer screen.Chapter 8 introduces the annotation — extra code that provides useful information about the nature of your program. In particular, Chapter 8 describes the Override
annotation.
In this chapter, Listing 9-9 introduces another type of annotation: the SuppressWarnings
annotation. When you use a SuppressWarnings
annotation, you tell Java not to remind you that your program contains certain questionable code. In Listing 9-9, the line @SuppressWarnings("serial")
tells Java not to remind you that you've omitted something called a serial
VersionUID
field. In other words, the SuppressWarnings
annotation tells Java not to display a warning like the one in Figure 9-5.
“And what,” you ask, “is a serialVersionUID
field?” It’s something having to do with extending the JFrame
class — something that you don’t care about. Not having a serialVersionUID
field generates a warning, not an error. So live dangerously! Just suppress the warning (with the annotation in Listing 9-9) and don’t worry about serialVersionUID
fields.
3.145.125.51