376 Chapter 11 Inheritance and Polymorphism
data fields 23
constructor 24 /** Set a new color */
25 public void setColor(String color) {
methods 26 this.color = color;
27 }
28
29 /** Return filled. Since filled is boolean,
30 its get method is named isFilled */
31 public boolean isFilled() {
32 return filled;
33 }
34
35 /** Set a new filled */
36 public void setFilled(boolean filled) {
37 this.filled = filled;
38 }
39
40 /** Get dateCreated */
41 public java.util.Date getDateCreated() {
42 return dateCreated;
43 }
44
45 /** Return a string representation of this object */
46 public String toString() {
47 return "created on " + dateCreated + "\ncolor: " + color +
48 " and filled: " + filled;
49 }
50 }
LISTING 11.2 Circle4.java
1 public class Circle4 extends GeometricObject1 {
2 private double radius;
3
4 public Circle4() {
5}
6
7 public Circle4(double radius) {
8 this.radius = radius;
9}
10
11 public Circle4(double radius, String color, boolean filled) {
12 this.radius = radius;
13 setColor(color);
14 setFilled(filled);
15 }
16
17 /** Return radius */
18 public double getRadius() {
19 return radius;
20 }
21
22 /** Set a new radius */
23 public void setRadius(double radius) {
24 this.radius = radius;
25 }
26
27 /** Return area */
28 public double getArea() {
29 return radius * radius * Math.PI;
30 }
11.2 Superclasses and Subclasses 377
31
32 /** Return diameter */
33 public double getDiameter() {
34 return 2 * radius;
35 }
36
37 /** Return perimeter */
38 public double getPerimeter() {
39 return 2 * radius * Math.PI;
40 }
41
42 /* Print the circle info */
43 public void printCircle() {
44 System.out.println("The circle is created " + getDateCreated() +
45 " and the radius is " + radius);
46 }
47 }
The Circle class extends the GeometricObject class (Listing 11.2) using the following
syntax:
Subclass Superclass
public class Circle extends GeometricObject
The keyword extends (line 1) tells the compiler that the Circle class extends the private member in base class
GeometricObject class, thus inheriting the methods getColor, setColor, isFilled,
setFilled, and toString.
The overloaded constructor Circle(double radius, string color, boolean
filled) is implemented by invoking the setColor and setFilled methods to set the
color and filled properties (lines 11–15). These two public methods are defined in the
base class GeometricObject and are inherited in Circle. So, they can be used in the
derived class.
You might attempt to use the data fields color and filled directly in the constructor as
follows:
public Circle4(double radius, String color, boolean filled) {
this.radius = radius;
this.color = color; // Illegal
this.filled = filled; // Illegal
}
This is wrong, because the private data fields color and filled in the Geometric-
Object class cannot be accessed in any class other than in the GeometricObject class
itself. The only way to read and modify color and filled is through their get and set
methods.
The Rectangle class (Listing 11.3) extends the GeometricObject class (Listing 11.2)
using the following syntax:
Subclass Superclass
public class Rectangle extends GeometricObject
378 Chapter 11 Inheritance and Polymorphism
data fields The keyword extends (line 1) tells the compiler that the Rectangle class extends the
constructor GeometricObject class, thus inheriting the methods getColor, setColor, isFilled,
setFilled, and toString.
methods
LISTING 11.3 Rectangle1.java
1 public class Rectangle1 extends GeometricObject1 {
2 private double width;
3 private double height;
4
5 public Rectangle1() {
6}
7
8 public Rectangle1(double width, double height) {
9 this.width = width;
10 this.height = height;
11 }
12
13 public Rectangle1(double width, double height, String color,
14 boolean filled) {
15 this.width = width;
16 this.height = height;
17 setColor(color);
18 setFilled(filled);
19 }
20
21 /** Return width */
22 public double getWidth() {
23 return width;
24 }
25
26 /** Set a new width */
27 public void setWidth(double width) {
28 this.width = width;
29 }
30
31 /** Return height */
32 public double getHeight() {
33 return height;
34 }
35
36 /** Set a new height */
37 public void setHeight(double height) {
38 this.height = height;
39 }
40
41 /** Return area */
42 public double getArea() {
43 return width * height;
44 }
45
46 /** Return perimeter */
47 public double getPerimeter() {
48 return 2 * (width + height);
49 }
50 }
The code in Listing 11.4 creates objects of Circle and Rectangle and invokes the methods
on these objects. The toString() method is inherited from the GeometricObject class
and is invoked from a Circle object (line 4) and a Rectangle object (line 10).
11.2 Superclasses and Subclasses 379
LISTING 11.4 TestCircleRectangle.java Circle object
invoke toString
1 public class TestCircleRectangle {
2 public static void main(String[] args) { Rectangle object
3 Circle4 circle = new Circle4(1); invoke toString
4 System.out.println("A circle " + circle.toString() );
5 System.out.println("The radius is " + circle.getRadius());
6 System.out.println("The area is " + circle.getArea());
7 System.out.println("The diameter is " + circle.getDiameter());
8
9 Rectangle1 rectangle = new Rectangle1(2, 4);
10 System.out.println("\nA rectangle " + rectangle.toString() );
11 System.out.println("The area is " + rectangle.getArea());
12 System.out.println("The perimeter is " +
13 rectangle.getPerimeter() );
14 }
15 }
A circle created on Thu Sep 24 20:31:02 EDT 2009
color: white and filled: false
The radius is 1.0
The area is 3.141592653589793
The diameter is 2.0
A rectangle created on Thu Sep 24 20:31:02 EDT 2009
color: white and filled: false
The area is 8.0
The perimeter is 12.0
The following points regarding inheritance are worthwhile to note:
■ Contrary to the conventional interpretation, a subclass is not a subset of its super-
class. In fact, a subclass usually contains more information and methods than its more in subclass
superclass.
■ Private data fields in a superclass are not accessible outside the class. Therefore, they private data fields
cannot be used directly in a subclass. They can, however, be accessed/mutated
through public accessor/mutator if defined in the superclass.
■ Not all is-a relationships should be modeled using inheritance. For example, a nonextensible is-a
square is a rectangle, but you should not define a Square class to extend a
Rectangle class, because there is nothing to extend (or supplement) from a rec-
tangle to a square. Rather you should define a Square class to extend the
GeometricObject class. For class A to extend class B, A should contain more
detailed information than B.
■ Inheritance is used to model the is-a relationship. Do not blindly extend a class just no blind extension
for the sake of reusing methods. For example, it makes no sense for a Tree class to
extend a Person class, even though they share common properties such as height
and weight. A subclass and its superclass must have the is-a relationship.
■ Some programming languages allow you to derive a subclass from several classes. multiple inheritance
This capability is known as multiple inheritance. Java, however, does not allow mul- single inheritance
tiple inheritance. A Java class may inherit directly from only one superclass. This
restriction is known as single inheritance. If you use the extends keyword to define
a subclass, it allows only one parent class. Nevertheless, multiple inheritance can be
achieved through interfaces, which will be introduced in §14.4, “Interfaces.”
380 Chapter 11 Inheritance and Polymorphism
11.3 Using the super Keyword
A subclass inherits accessible data fields and methods from its superclass. Does it inherit con-
structors? Can superclass constructors be invoked from subclasses? This section addresses
these questions and their ramification.
§10.4, “The this Reference,” introduced the use of the keyword this to reference the
calling object. The keyword super refers to the superclass of the class in which super
appears. It can be used in two ways:
■ To call a superclass constructor.
■ To call a superclass method.
11.3.1 Calling Superclass Constructors
The syntax to call a superclass constructor is:
super(), or super(parameters);
The statement super() invokes the no-arg constructor of its superclass, and the statement
super(arguments) invokes the superclass constructor that matches the arguments. The
statement super() or super(arguments) must appear in the first line of the subclass con-
structor; this is the only way to explicitly invoke a superclass constructor. For example, the
constructor in lines 11–15 in Listing 11.2 can be replaced by the following code:
public Circle4(double radius, String color, boolean filled) {
super(color, filled);
this.radius = radius;
}
Caution
You must use the keyword super to call the superclass constructor, and the call must be the first
statement in the constructor. Invoking a superclass constructor’s name in a subclass causes a
syntax error.
Note
A constructor is used to construct an instance of a class. Unlike properties and methods, the con-
structors of a superclass are not inherited in the subclass. They can only be invoked from the con-
structors of the subclasses, using the keyword super.
11.3.2 Constructor Chaining
A constructor may invoke an overloaded constructor or its superclass constructor. If neither is
invoked explicitly, the compiler automatically puts super() as the first statement in the con-
structor. For example,
public ClassName() { Equivalent public ClassName() {
// some statements Equivalent super();
// some statements
}
}
public ClassName(double d) {
// some statements public ClassName(double d) {
super();
} // some statements
}
11.3 Using the super Keyword 381
In any case, constructing an instance of a class invokes the constructors of all the superclasses constructor chaining
along the inheritance chain. When constructing an object of a subclass, the subclass construc-
tor first invokes its superclass constructor before performing its own tasks. If the superclass is
derived from another class, the superclass constructor invokes its parent-class constructor
before performing its own tasks. This process continues until the last constructor along the
inheritance hierarchy is called. This is constructor chaining.
Consider the following code:
1 public class Faculty extends Employee { invoke overloaded
2 public static void main(String[] args) { constructor
3 new Faculty();
4}
5
6 public Faculty() {
7 System.out.println("(4) Performs Faculty's tasks");
8}
9}
10
11 class Employee extends Person {
12 public Employee() {
13 this("(2) Invoke Employee's overloaded constructor");
14 System.out.println("(3) Performs Employee's tasks ");
15 }
16
17 public Employee(String s) {
18 System.out.println(s);
19 }
20 }
21
22 class Person {
23 public Person() {
24 System.out.println("(1) Performs Person's tasks");
25 }
26 }
(1) Performs Person's tasks
(2) Invoke Employee's overloaded constructor
(3) Performs Employee's tasks
(4) Performs Faculty's tasks
The program produces the preceding output. Why? Let us discuss the reason. In line 3, new
Faculty() invokes Faculty’s no-arg constructor. Since Faculty is a subclass of
Employee, Employee’s no-arg constructor is invoked before any statements in Faculty’s
constructor are executed. Employee’s no-arg constructor invokes Employee’s second con-
structor (line 12). Since Employee is a subclass of Person, Person’s no-arg constructor is
invoked before any statements in Employee’s second constructor are executed. This process
is pictured in the figure below.
Faculty() Employee() Employee(String s) Person()
{ { this("(2) ..."); { {
Performs Faculty's Performs Employee's Performs Employee's Performs Person's
tasks; tasks; tasks; tasks;
} } } }
382 Chapter 11 Inheritance and Polymorphism
no-arg constructor Caution
no-arg constructor
If a class is designed to be extended, it is better to provide a no-arg constructor to avoid pro-
method overriding gramming errors. Consider the following code:
toString in superclass
1 public class Apple extends Fruit {
2}
3
4 class Fruit {
5 public Fruit(String name) {
6 System.out.println("Fruit's constructor is invoked");
7}
8}
Since no constructor is explicitly defined in Apple, Apple’s default no-arg constructor is
defined implicitly. Since Apple is a subclass of Fruit, Apple’s default constructor automati-
cally invokes Fruit’s no-arg constructor. However, Fruit does not have a no-arg constructor,
because Fruit has an explicit constructor defined. Therefore, the program cannot be compiled.
Design Guide
It is better to provide a no-arg constructor (if desirable) for every class to make the class easy to
extend and to avoid errors.
11.3.3 Calling Superclass Methods
The keyword super can also be used to reference a method other than the constructor in the
superclass. The syntax is like this:
super.method(parameters);
You could rewrite the printCircle() method in the Circle class as follows:
public void printCircle() {
System.out.println("The circle is created " +
super.getDateCreated() + " and the radius is " + radius);
}
It is not necessary to put super before getDateCreated() in this case, however, because
getDateCreated is a method in the GeometricObject class and is inherited by the
Circle class. Nevertheless, in some cases, as shown in the next section, the keyword super
is needed.
11.4 Overriding Methods
A subclass inherits methods from a superclass. Sometimes it is necessary for the subclass to
modify the implementation of a method defined in the superclass. This is referred to as
method overriding.
The toString method in the GeometricObject class returns the string representation
for a geometric object. This method can be overridden to return the string representation for a
circle. To override it, add the following new method in Listing 11.2, Circle4.java:
1 public class Circle4 extends GeometricObject1 {
2 // Other methods are omitted
3
4 /** Override the toString method defined in GeometricObject */
5 public String toString() {
6 return super.toString() + "\nradius is " + radius;
7}
8}
11.5 Overriding vs. Overloading 383
The toString() method is defined in the GeometricObject class and modified in the Circle no super.super.
class. Both methods can be used in the Circle class. To invoke the toString method defined in methodName()
the GeometricObject class from the Circle class, use super.toString() (line 6).
Can a subclass of Circle access the toString method defined in the GeometricObject
class using a syntax such as super.super.toString()? No. This is a syntax error.
Several points are worth noting:
■ An instance method can be overridden only if it is accessible. Thus a private method override accessible instance
cannot be overridden, because it is not accessible outside its own class. If a method method
defined in a subclass is private in its superclass, the two methods are completely
unrelated.
■ Like an instance method, a static method can be inherited. However, a static method cannot override static method
cannot be overridden. If a static method defined in the superclass is redefined in a
subclass, the method defined in the superclass is hidden. The hidden static methods
can be invoked using the syntax SuperClassName.staticMethodName.
11.5 Overriding vs. Overloading
You have learned about overloading methods in §5.8. Overloading means to define multiple
methods with the same name but different signatures. Overriding means to provide a new
implementation for a method in the subclass. The method is already defined in the
superclass.
To override a method, the method must be defined in the subclass using the same signature
and the same return type.
Let us use an example to show the differences between overriding and overloading. In (a)
below, the method p(double i) in class A overrides the same method defined in class B. In
(b), however, the class B has two overloaded methods p(double i) and p(int i). The
method p(double i) is inherited from B.
public class Test { public class Test {
public static void main(String[] args) { public static void main(String[] args) {
A a = new A(); A a = new A();
a.p(10); a.p(10);
a.p(10.0); a.p(10.0);
} }
} }
class B { class B {
public void p(double i) { public void p(double i) {
System.out.println(i * 2); System.out.println(i * 2);
} }
} }
class A extends B { class A extends B {
// This method overrides the method in B // This method overloads the method in B
public void p(double i ) { public void p(int i ) {
System.out.println(i); System.out.println(i);
} }
} }
(a) (b)
When you run the Test class in (a), both a.p(10) and a.p(10.0) invoke the p(double i)
method defined in class A to display 10.0. When you run the Test class in (b), a.p(10)
invokes the p(int i) method defined in class B to display 20, and a.p(10.0) invokes the
p(double i) method defined in class A to display 10.0.
384 Chapter 11 Inheritance and Polymorphism
11.6 The Object Class and Its toString() Method
Every class in Java is descended from the java.lang.Object class. If no inheritance is
specified when a class is defined, the superclass of the class is Object by default. For exam-
ple, the following two class definitions are the same:
public class ClassName { Equivalent public class ClassName extends Object {
... ...
} }
toString() Classes such as String, StringBuilder, Loan, and GeometricObject are implicitly sub-
string representation classes of Object (as are all the main classes you have seen in this book so far). It is important
to be familiar with the methods provided by the Object class so that you can use them in your
print object classes. We will introduce the toString method in the Object class in this section.
subtype The signature of the toString() method is
supertype
public String toString()
Invoking toString() on an object returns a string that describes the object. By default, it
returns a string consisting of a class name of which the object is an instance, an at sign (@),
and the object’s memory address in hexadecimal. For example, consider the following code
for the Loan class defined in Listing 10.2:
Loan loan = new Loan();
System.out.println(loan.toString());
The code displays something like Loan@15037e5. This message is not very helpful or infor-
mative. Usually you should override the toString method so that it returns a descriptive
string representation of the object. For example, the toString method in the Object class
was overridden in the GeometricObject class in lines 46-49 in Listing 11.1 as follows:
public String toString() {
return "created on " + dateCreated + "\ncolor: " + color +
" and filled: " + filled;
}
Note
You can also pass an object to invoke System.out.println(object) or System.out.
print(object). This is equivalent to invoking System.out.println(object.toString())
or System.out.print(object.toString()). So you could replace System.out.println-
(loan.toString()) with System.out.println(loan).
11.7 Polymorphism
The three pillars of object-oriented programming are encapsulation, inheritance, and
polymorphism. You have already learned the first two. This section introduces
polymorphism.
First let us define two useful terms: subtype and supertype. A class defines a type. A type
defined by a subclass is called a subtype and a type defined by its superclass is called a supertype.
So, you can say that Circle is a subtype of GeometricObject and GeometricObject is a
supertype for Circle.
11.8 Dynamic Binding 385
The inheritance relationship enables a subclass to inherit features from its superclass with
additional new features. A subclass is a specialization of its superclass; every instance of a
subclass is also an instance of its superclass, but not vice versa. For example, every circle is a
geometric object, but not every geometric object is a circle. Therefore, you can always pass an
instance of a subclass to a parameter of its superclass type. Consider the code in Listing 11.5.
LISTING 11.5 PolymorphismDemo.java polymorphic call
polymorphic call
1 public class PolymorphismDemo {
2 /** Main method */
3 public static void main(String[] args) {
4 // Display circle and rectangle properties
5 displayObject(new Circle4(1, "red", false));
6 displayObject(new Rectangle1(1, 1, "black", true));
7}
8
9 /** Display geometric object properties */
10 public static void displayObject(GeometricObject1 object) {
11 System.out.println("Created on " + object.getDateCreated() +
12 ". Color is " + object.getColor());
13 }
14 }
Created on Mon Mar 09 19:25:20 EDT 2009. Color is white
Created on Mon Mar 09 19:25:20 EDT 2009. Color is black
Method displayObject (line 10) takes a parameter of the GeometricObject type. You what is polymorphism?
can invoke displayObject by passing any instance of GeometricObject (e.g., new Cir-
cle4(1, "red", false) and new Rectangle1(1, 1, "black", false) in lines 5–6). An
object of a subclass can be used wherever its superclass object is used. This is commonly known
as polymorphism (from a Greek word meaning “many forms”). In simple terms, polymorphism
means that a variable of a supertype can refer to a subtype object.
11.8 Dynamic Binding
A method may be defined in a superclass and overridden in its subclass. For example, the
toString() method is defined in the Object class and overridden in GeometricObject1.
Consider the following code:
Object o = new GeometricObject();
System.out.println(o.toString());
Which toString() method is invoked by o? To answer this question, we first introduce two declared type
terms: declared type and actual type. A variable must be declared a type. The type of a vari- actual type
able is called its declared type. Here o’s declared type is Object. A variable of a reference
type can hold a null value or a reference to an instance of the declared type. The instance dynamic binding
may be created using the constructor of the declared type or its subtype. The actual type of the
variable is the actual class for the object referenced by the variable. Here o’s actual type is
GeometricObject, since o references to an object created using new GeometricOb-
ject(). Which toString() method is invoked by o is determined by o’s actual type. This
is known as dynamic binding.
Dynamic binding works as follows: Suppose an object o is an instance of classes C1, C2,
Á , Cn-1, and Cn, where C1 is a subclass of C2, C2 is a subclass of C3, Á , and Cn-1 is a subclass
of Cn, as shown in Figure 11.2. That is, Cn is the most general class, and C1 is the most specific
386 Chapter 11 Inheritance and Polymorphism
Cn Cn-1 ..... C2 C1
java.lang.Object If o is an instance of C1, o is also an
instance of C2, C3, …, Cn-1, and Cn
FIGURE 11.2 The method to be invoked is dynamically bound at runtime.
Video Note class. In Java, Cn is the Object class. If o invokes a method p, the JVM searches the imple-
polymorphism and dynamic mentation for the method p in C1, C2, Á , Cn-1, and Cn, in this order, until it is found. Once an
binding demo implementation is found, the search stops and the first-found implementation is invoked.
polymorphic call
Listing 11.6 gives an example to demonstrate dynamic binding.
dynamic binding
LISTING 11.6 DynamicBindingDemo.java
override toString()
1 public class DynamicBindingDemo {
override toString() 2 public static void main(String[] args) {
3 m(new GraduateStudent());
4 m(new Student());
5 m(new Person());
6 m(new Object());
7}
8
9 public static void m(Object x) {
10 System.out.println(x.toString());
11 }
12 }
13
14 class GraduateStudent extends Student {
15 }
16
17 class Student extends Person {
18 public String toString() {
19 return "Student";
20 }
21 }
22
23 class Person extends Object {
24 public String toString() {
25 return "Person";
26 }
27 }
Student
Student
Person
java.lang.Object@130c19b
Method m (line 9) takes a parameter of the Object type. You can invoke m with any object
(e.g., new GraduateStudent(), new Student(), new Person(), and new Object()) in
lines 3–6).
When the method m(Object x) is executed, the argument x’s toString method is
invoked. x may be an instance of GraduateStudent, Student, Person, or Object. Classes
GraduateStudent, Student, Person, and Object have their own implementations of the
toString method. Which implementation is used will be determined by x’s actual type at
runtime. Invoking m(new GraduateStudent()) (line 3) causes the toString method
defined in the Student class to be invoked.
11.9 Casting Objects and the instanceof Operator 387
Invoking m(new Student()) (line 4) causes the toString method defined in the matching vs. binding
Student class to be invoked.
Invoking m(new Person()) (line 5) causes the toString method defined in the Person
class to be invoked. Invoking m(new Object()) (line 6) causes the toString method
defined in the Object class to be invoked.
Matching a method signature and binding a method implementation are two separate
issues. The declared type of the reference variable decides which method to match at compile
time. The compiler finds a matching method according to parameter type, number of parame-
ters, and order of the parameters at compile time. A method may be implemented in several
subclasses. The JVM dynamically binds the implementation of the method at runtime,
decided by the actual type of the variable.
11.9 Casting Objects and the instanceof Operator
You have already used the casting operator to convert variables of one primitive type to
another. Casting can also be used to convert an object of one class type to another within an
inheritance hierarchy. In the preceding section, the statement
m(new Student());
assigns the object new Student() to a parameter of the Object type. This statement is
equivalent to
Object o = new Student(); // Implicit casting
m(o);
The statement Object o = new Student(), known as implicit casting, is legal because an implicit casting
instance of Student is automatically an instance of Object.
Suppose you want to assign the object reference o to a variable of the Student type using
the following statement:
Student b = o;
In this case a compile error would occur. Why does the statement Object o = new Stu- explicit casting
dent() work but Student b = o doesn’t? The reason is that a Student object is always an
instance of Object, but an Object is not necessarily an instance of Student. Even though
you can see that o is really a Student object, the compiler is not clever enough to know it. To
tell the compiler that o is a Student object, use an explicit casting. The syntax is similar to
the one used for casting among primitive data types. Enclose the target object type in paren-
theses and place it before the object to be cast, as follows:
Student b = (Student)o; // Explicit casting
It is always possible to cast an instance of a subclass to a variable of a superclass (known as upcasting
upcasting), because an instance of a subclass is always an instance of its superclass. When downcasting
casting an instance of a superclass to a variable of its subclass (known as downcasting),
explicit casting must be used to confirm your intention to the compiler with the ClassCastException
(SubclassName) cast notation. For the casting to be successful, you must make sure that the instanceof
object to be cast is an instance of the subclass. If the superclass object is not an instance of the
subclass, a runtime ClassCastException occurs. For example, if an object is not an
instance of Student, it cannot be cast into a variable of Student. It is a good practice, there-
fore, to ensure that the object is an instance of another object before attempting a casting. This
can be accomplished by using the instanceof operator. Consider the following code:
Object myObject = new Circle();
... // Some lines of code
388 Chapter 11 Inheritance and Polymorphism
/** Perform casting if myObject is an instance of Circle */
if (myObject instanceof Circle) {
System.out.println("The circle diameter is " +
((Circle)myObject) .getDiameter());
...
}
You may be wondering why casting is necessary. Variable myObject is declared Object.
The declared type decides which method to match at compile time. Using
myObject.getDiameter() would cause a compile error, because the Object class does
not have the getDiameter method. The compiler cannot find a match for
myObject.getDiameter(). It is necessary to cast myObject into the Circle type to tell
the compiler that myObject is also an instance of Circle.
Why not define myObject as a Circle type in the first place? To enable generic programming,
it is a good practice to define a variable with a supertype, which can accept a value of any subtype.
lowercase keywords Note
instanceof is a Java keyword. Every letter in a Java keyword is in lowercase.
casting analogy Tip
polymorphic call To help understand casting, you may also consider the analogy of fruit, apple, and orange with
polymorphic call the Fruit class as the superclass for Apple and Orange. An apple is a fruit, so you can always
safely assign an instance of Apple to a variable for Fruit. However, a fruit is not necessarily an
apple, so you have to use explicit casting to assign an instance of Fruit to a variable of Apple.
Listing 11.7 demonstrates polymorphism and casting. The program creates two objects
(lines 5–6), a circle and a rectangle, and invokes the displayObject method to display them
(lines 9–10). The displayObject method displays the area and diameter if the object is a
circle (line 15), and the area if the object is a rectangle (line 21).
LISTING 11.7 CastingDemo.java
1 public class CastingDemo {
2 /** Main method */
3 public static void main(String[] args) {
4 // Create and initialize two objects
5 Object object1 = new Circle4(1);
6 Object object2 = new Rectangle1(1, 1);
7
8 // Display circle and rectangle
9 displayObject(object1);
10 displayObject(object2);
11 }
12
13 /** A method for displaying an object */
14 public static void displayObject(Object object) {
15 if (object instanceof Circle4 ) {
16 System.out.println("The circle area is " +
17 ((Circle4)object).getArea());
18 System.out.println("The circle diameter is " +
19 ((Circle4)object).getDiameter());
20 }
21 else if (object instanceof Rectangle1 ) {
22 System.out.println("The rectangle area is " +
23 ((Rectangle1)object).getArea());
24 }
25 }
26 }
11.10 The Object’s equals Method 389
The circle area is 3.141592653589793
The circle diameter is 2.0
The rectangle area is 1.0
The displayObject(Object object) method is an example of generic programming. It
can be invoked by passing any instance of Object.
The program uses implicit casting to assign a Circle object to object1 and a
Rectangle object to object2 (lines 5–6), then invokes the displayObject method to dis-
play the information on these objects (lines 9–10).
In the displayObject method (lines 14–25), explicit casting is used to cast the object to
Circle if the object is an instance of Circle, and the methods getArea and getDiameter
are used to display the area and diameter of the circle.
Casting can be done only when the source object is an instance of the target class. The pro-
gram uses the instanceof operator to ensure that the source object is an instance of the tar-
get class before performing a casting (line 15).
Explicit casting to Circle (lines 17, 19) and to Rectangle (line 23) is necessary because
the getArea and getDiameter methods are not available in the Object class.
Caution . precedes casting
The object member access operator (.) precedes the casting operator. Use parentheses to ensure
that casting is done before the . operator, as in
((Circle)object).getArea());
11.10 The Object’s equals Method
Another method defined in the Object class that is often used is the equals method. Its equals(Object)
signature is
public boolean equals(Object o)
This method tests whether two objects are equal. The syntax for invoking it is:
object1.equals(object2);
The default implementation of the equals method in the Object class is:
public boolean equals(Object obj) {
return (this == obj);
}
This implementation checks whether two reference variables point to the same object using
the == operator. You should override this method in your custom class to test whether two dis-
tinct objects have the same content.
You have already used the equals method to compare two strings in §9.2, “The String
Class.” The equals method in the String class is inherited from the Object class and is
overridden in the String class to test whether two strings are identical in content. You can
override the equals method in the Circle class to compare whether two circles are equal
based on their radius as follows:
public boolean equals(Object o) {
if (o instanceof Circle) {
return radius == ((Circle)o).radius;
}
390 Chapter 11 Inheritance and Polymorphism
else
return false;
}
== vs. equals Note
The == comparison operator is used for comparing two primitive data type values or for deter-
mining whether two objects have the same references. The equals method is intended to test
whether two objects have the same contents, provided that the method is overridden in the
defining class of the objects. The == operator is stronger than the equals method, in that the
== operator checks whether the two reference variables refer to the same object.
equals(Object) Caution
Using the signature equals(SomeClassName obj) (e.g., equals(Circle c)) to over-
ride the equals method in a subclass is a common mistake. You should use equals(Object
obj). See Review Question 11.15.
Video Note 11.11 The ArrayList Class
the ArrayList class
Now we are ready to introduce a very useful class for storing objects. You can create an array
to store objects. But, once the array is created, its size is fixed. Java provides the ArrayList
class that can be used to store an unlimited number of objects. Figure 11.3 shows some meth-
ods in ArrayList.
java.util.ArrayList Creates an empty list.
Appends a new element o at the end of this list.
+ArrayList() Adds a new element o at the specified index in this list.
+add(o: Object): void Removes all the elements from this list.
+add(index: int, o: Object): void Returns true if this list contains the element o.
+clear(): void Returns the element from this list at the specified index.
+contains(o: Object): boolean Returns the index of the first matching element in this list.
+get(index: int): Object Returns true if this list contains no elements.
+indexOf(o: Object): int Returns the index of the last matching element in this list.
+isEmpty(): boolean Removes the element o from this list.
+lastIndexOf(o: Object): int Returns the number of elements in this list.
+remove(o: Object): boolean Removes the element at the specified index.
+size(): int Sets the element at the specified index.
+remove(index: int): boolean
+set(index: int, o: Object): Object
FIGURE 11.3 An ArrayList stores an unlimited number of objects.
create ArrayList Listing 11.8 gives an example of using ArrayList to store objects.
add element
LISTING 11.8 TestArrayList.java
1 public class TestArrayList {
2 public static void main(String[] args) {
3 // Create a list to store cities
4 java.util.ArrayList cityList = new java.util.ArrayList();
5
6 // Add some cities in the list
7 cityList.add("London");
11.11 The ArrayList Class 391
8 // cityList now contains [London] list size
9 cityList.add("Denver"); contains element?
10 // cityList now contains [London, Denver] element index
11 cityList.add("Paris"); is empty?
12 // cityList now contains [London, Denver, Paris]
13 cityList.add("Miami"); remove element
14 // cityList now contains [London, Denver, Paris, Miami] remove element
15 cityList.add("Seoul"); toString()
16 // contains [London, Denver, Paris, Miami, Seoul] get element
17 cityList.add("Tokyo"); create ArrayList
18 // contains [London, Denver, Paris, Miami, Seoul, Tokyo]
19
20 System.out.println("List size? " + cityList.size() );
21 System.out.println("Is Miami in the list? " +
22 cityList.contains("Miami") );
23 System.out.println("The location of Denver in the list? "
24 + cityList.indexOf("Denver"));
25 System.out.println("Is the list empty? " +
26 cityList.isEmpty() ); // Print false
27
28 // Insert a new city at index 2
29 cityList.add(2, "Xian");
30 // contains [London, Denver, Xian, Paris, Miami, Seoul, Tokyo]
31
32 // Remove a city from the list
33 cityList.remove("Miami");
34 // contains [London, Denver, Xian, Paris, Seoul, Tokyo]
35
36 // Remove a city at index 1
37 cityList.remove(1);
38 // contains [London, Xian, Paris, Seoul, Tokyo]
39
40 // Display the contents in the list
41 System.out.println(cityList.toString());
42
43 // Display the contents in the list in reverse order
44 for (int i = cityList.size() - 1; i >= 0; i--)
45 System.out.print(cityList.get(i) + " ");
46 System.out.println();
47
48 // Create a list to store two circles
49 java.util.ArrayList list = new java.util.ArrayList();
50
51 // Add two circles
52 list.add(new Circle4(2));
53 list.add(new Circle4(3));
54
55 // Display the area of the first circle in the list
56 System.out.println("The area of the circle? " +
57 ((Circle4)list.get(0)).getArea());
58 }
59 }
List size? 6
Is Miami in the list? true
The location of Denver in the list? 1
Is the list empty? false
[London, Xian, Paris, Seoul, Tokyo]
Tokyo Seoul Paris Xian London
The area of the circle? 12.566370614359172
392 Chapter 11 Inheritance and Polymorphism
add(Object) The program creates an ArrayList using its no-arg constructor (line 4). The add method
adds any instance of Object into the list. Since String is a subclass of Object, strings can
size() be added to the list. The add method (lines 7–17) adds an object to the end of list. So, after
add(index, Object) cityList.add("London") (line 7), the list contains
remove(Object)
remove(index) [London]
toString() After cityList. add("Denver") (line 9), the list contains
getIndex()
[London, Denver]
After adding Paris, Miami, Seoul, and Tokyo (lines 11–17), the list would contain
[London, Denver, Paris, Miami, Seoul, Tokyo]
Invoking size() (line 20) returns the size of the list, which is currently 6. Invoking
contains("Miami") (line 22) checks whether the object is in the list. In this case, it returns
true, since Miami is in the list. Invoking indexOf("Denver") (line 24) returns the index
of the object in the list, which is 1. If the object is not in the list, it returns -1. The isEmpty()
method (line 26) checks whether the list is empty. It returns false, since the list is not empty.
The statement cityList.add(2, "Xian") (line 29) inserts an object to the list at the
specified index. After this statement, the list becomes
[London, Denver, Xian, Paris, Miami, Seoul, Tokyo]
The statement cityList. remove("Miami") (line 33) removes the object from the list.
After this statement, the list becomes
[London, Denver, Xian, Paris, Seoul, Tokyo]
The statement cityList. remove(1) (line 37) removes the object at the specified index
from the list. After this statement, the list becomes
[London, Xian, Paris, Seoul, Tokyo]
The statement in line 41 is same as
System.out.println(cityList);
The toString() method returns a string representation for the list in the form of
[e0.toString(), e1.toString(), ..., ek.toString()], where e0, e1, Á , and ek
are the elements in the list.
The get(index) method (line 45) returns the object at the specified index.
compiler warning Note
array vs. ArrayList
You will get the following warning when compiling this program from the command prompt:
Note: TestArrayList.java uses unchecked or unsafe operations.
Note: Recompile with –Xlint:unchecked for details.
This warning can be eliminated using generic types discussed in Chapter 21, “Generics”. For now,
ignore it. Despite the warning, the program will be compiled just fine to produce a .class file.
ArrayList objects can be used like arrays, but there are many differences. Table 11.1 lists
their similarities and differences.
Once an array is created, its size is fixed. You can access an array element using the
square-bracket notation (e.g., a[index]). When an ArrayList is created, its size is 0. You
cannot use the get and set methods if the element is not in the list. It is easy to add, insert,
11.12 A Custom Stack Class 393
TABLE 11.1 Differences and Similarities between Arrays and ArrayList
Operation Array ArrayList
Creating an array/ArrayList Object[] a = new Object[10] ArrayList list = new ArrayList();
Accessing an element
Updating an element a[index] list.get(index);
Returning size
Adding a new element a[index] = "London"; list.set(index, "London");
Inserting a new element
Removing an element a.length list.size();
Removing an element
Removing all elements list.add("London");
list.add(index, "London");
list.remove(index);
list.remove(Object);
list.clear();
and remove elements in a list, but it is rather complex to add, insert, and remove elements in
an array. You have to write code to manipulate the array in order to perform these operations.
Note Vector class
java.util.Vector is also a class for storing objects, which is very similar to the ArrayList
class. All the methods in ArrayList are also available in Vector. The Vector class was
introduced in JDK 1.1. The ArrayList class introduced in JDK 1.2 was intended to replace the
Vector class.
11.12 A Custom Stack Class Video Note
the MyStack class
“Designing a Class for Stacks” in §10.8 presented a stack class for storing int values. This
section introduces a stack class to store objects. You can use an ArrayList to implement
Stack, as shown in Listing 11.9. The UML diagram for the class is shown in Figure 11.4.
MyStack A list to store elements.
-list: ArrayList Returns true if this stack is empty.
Returns the number of elements in this stack.
+isEmpty(): boolean Returns the top element in this stack.
+getSize(): int Returns and removes the top element in this stack.
+peek(): Object Adds a new element to the top of this stack.
+pop(): Object Returns the position of the first element in the stack from
+push(o: Object): void
+search(o: Object): int the top that matches the specified element.
FIGURE 11.4 The MyStack class encapsulates the stack storage and provides the operations
for manipulating the stack.
LISTING 11.9 MyStack.java array list
stack empty?
1 public class MyStack {
2 private java.util.ArrayList list = new java.util.ArrayList();
3
4 public boolean isEmpty() {
5 return list.isEmpty();
6}
394 Chapter 11 Inheritance and Polymorphism
get stack size 7
peek stack 8 public int getSize() {
remove 9 return list.size();
10 }
push 11
search 12 public Object peek() {
13 return list.get(getSize() - 1);
14 }
15
16 public Object pop() {
17 Object o = list.get(getSize() - 1);
18 list.remove(getSize() - 1);
19 return o;
20 }
21
22 public void push(Object o) {
23 list.add(o);
24 }
25
26 public int search(Object o) {
27 return list.lastIndexOf(o);
28 }
29
30 /** Override the toString in the Object class */
31 public String toString() {
32 return "stack: " + list.toString();
33 }
34 }
An array list is created to store the elements in the stack (line 2). The isEmpty() method
(lines 4–6) returns list.isEmpty(). The getSize() method (lines 8–10) returns
list.size(). The peek() method (lines 12–14) retrieves the element at the top of the stack
without removing it. The end of the list is the top of the stack. The pop() method (lines
16–20) removes the top element from the stack and returns it. The push(Object element)
method (lines 22–24) adds the specified element to the stack. The search(Object ele-
ment) method checks whether the specified element is in the stack, and it returns the index of
first-matching element in the stack from the top by invoking list.lastIndexOf(o). The
toString() method (lines 31–33) defined in the Object class is overridden to display the
contents of the stack by invoking list.toString(). The toString() method imple-
mented in ArrayList returns a string representation of all the elements in an array list.
composition Design Guide
has-a
is-a In Listing 11.9, MyStack contains ArrayList. The relationship between MyStack and
ArrayList is composition. While inheritance models an is-a relationship, composition models a
has-a relationship. You may also implement MyStack as a subclass of ArrayList (see Exercise
11.4). Using composition is better, however, because it enables you to define a completely new
stack class without inheriting the unnecessary and inappropriate methods from ArrayList.
why protected? 11.13 The protected Data and Methods
So far you have used the private and public keywords to specify whether data fields and
methods can be accessed from the outside of the class. Private members can be accessed only
from the inside of the class, and public members can be accessed from any other classes.
Often it is desirable to allow subclasses to access data fields or methods defined in the
superclass, but not allow nonsubclasses to access these data fields and methods. To do so, you
can use the protected keyword. A protected data field or method in a superclass can be
accessed in its subclasses.
11.13 The protected Data and Methods 395
The modifiers private, protected, and public are known as visibility or accessibility
modifiers because they specify how class and class members are accessed. The visibility of
these modifiers increases in this order:
Visibility increases
private, none (if no modifier is used), protected, public
Table 11.2 summarizes the accessibility of the members in a class. Figure 11.5 illustrates how
a public, protected, default, and private datum or method in class C1 can be accessed from a
class C2 in the same package, from a subclass C3 in the same package, from a subclass C4 in
a different package, and from a class C5 in a different package.
TABLE 11.2 Data and Methods Visibility
Modifier Accessed Accessed Accessed Accessed
on members from the from the from a from a different
same class same package subclass
in a class package
public ✓ ✓ ✓ ✓
–
protected ✓ ✓ ✓ –
–
(default) ✓ ✓ –
private ✓ – –
package p1; public class C2 {
C1 o = new C1();
public class C1 { can access o.x;
public int x; can access o.y;
protected int y; can access o.z;
int z; cannot access o.u;
private int u;
can invoke o.m();
protected void m() { }
}
}
public class C3 package p2; public class C5 {
extends C1 { C1 o = new C1();
public class C4 can access o.x;
can access x; extends C1 { cannot access o.y;
can access y; cannot access o.z;
can access z; can access x; cannot access o.u;
cannot access u; can access y;
cannot access z; cannot invoke o.m();
can invoke m(); cannot access u; }
}
can invoke m();
}
FIGURE 11.5 Visibility modifiers are used to control how data and methods are accessed.
Use the private modifier to hide the members of the class completely so that they cannot
be accessed directly from outside the class. Use no modifiers in order to allow the members of
the class to be accessed directly from any class within the same package but not from other
396 Chapter 11 Inheritance and Polymorphism
packages. Use the protected modifier to enable the members of the class to be accessed by
the subclasses in any package or classes in the same package. Use the public modifier to
enable the members of the class to be accessed by any class.
Your class can be used in two ways: for creating instances of the class, and for defining
subclasses by extending the class. Make the members private if they are not intended for
use from outside the class. Make the members public if they are intended for the users of the
class. Make the fields or methods protected if they are intended for the extenders of the
class but not the users of the class.
The private and protected modifiers can be used only for members of the class. The
public modifier and the default modifier (i.e., no modifier) can be used on members of the
class as well on the class. A class with no modifier (i.e., not a public class) is not accessible by
classes from other packages.
change visibility Note
A subclass may override a protected method in its superclass and change its visibility to public.
However, a subclass cannot weaken the accessibility of a method defined in the superclass. For
example, if a method is defined as public in the superclass, it must be defined as public in the
subclass.
11.14 Preventing Extending and Overriding
You may occasionally want to prevent classes from being extended. In such cases, use the
final modifier to indicate that a class is final and cannot be a parent class. The Math class is
a final class. The String, StringBuilder, and StringBuffer classes are also final
classes. For example, the following class is final and cannot be extended:
public final class C {
// Data fields, constructors, and methods omitted
}
You also can define a method to be final; a final method cannot be overridden by its sub-
classes.
For example, the following method is final and cannot be overridden:
public class Test {
// Data fields, constructors, and methods omitted
public final void m() {
// Do something
}
}
Note
The modifiers are used on classes and class members (data and methods), except that the final
modifier can also be used on local variables in a method. A final local variable is a constant inside
a method.
KEY TERMS constructor chaining 381
declared type 385
actual type 385 dynamic binding 385
array list 393 final 396
casting objects 387
composition 394
Chapter Summary 397
has-a relationship 394 protected 394
inheritance 374 subclass 375
instanceof 387 subtype 384
is-a relationship 394 superclass 375
override 382 supertype 384
polymorphism 385 vector 393
CHAPTER SUMMARY
1. You can derive a new class from an existing class. This is known as class inheritance.
The new class is called a subclass, child class or extended class. The existing class is
called a superclass, parent class, or base class.
2. A constructor is used to construct an instance of a class. Unlike properties and
methods, the constructors of a superclass are not inherited in the subclass. They
can be invoked only from the constructors of the subclasses, using the keyword
super.
3. A constructor may invoke an overloaded constructor or its superclass’s constructor.
The call must be the first statement in the constructor. If none of them is invoked
explicitly, the compiler puts super() as the first statement in the constructor, which
invokes the superclass’s no-arg constructor.
4. To override a method, the method must be defined in the subclass using the same sig-
nature as in its superclass.
5. An instance method can be overridden only if it is accessible. Thus a private method
cannot be overridden, because it is not accessible outside its own class. If a method
defined in a subclass is private in its superclass, the two methods are completely
unrelated.
6. Like an instance method, a static method can be inherited. However, a static method
cannot be overridden. If a static method defined in the superclass is redefined in a
subclass, the method defined in the superclass is hidden.
7. Every class in Java is descended from the java.lang.Object class. If no inheri-
tance is specified when a class is defined, its superclass is Object.
8. If a method’s parameter type is a superclass (e.g., Object), you may pass an object
to this method of any of the parameter’s subclasses (e.g., Circle or String). When
an object (e.g., a Circle object or a String object) is used in the method, the par-
ticular implementation of the method of the object that is invoked (e.g., toString)
is determined dynamically.
9. It is always possible to cast an instance of a subclass to a variable of a superclass,
because an instance of a subclass is always an instance of its superclass. When
casting an instance of a superclass to a variable of its subclass, explicit casting
must be used to confirm your intention to the compiler with the (SubclassName)
cast notation.
10. A class defines a type. A type defined by a subclass is called a subtype and a type
defined by its superclass is called a supertype.
11. When invoking an instance method from a reference variable, the actual type of the
variable decides which implementation of the method is used at runtime. When
398 Chapter 11 Inheritance and Polymorphism
accessing a field or a static method, the declared type of the reference variable
decides which method is used at compile time.
12. You can use obj instanceof AClass to test whether an object is an instance of a
class.
13. You can use the protected modifier to prevent the data and methods from being
accessed by nonsubclasses from a different package.
14. You can use the final modifier to indicate that a class is final and cannot be a par-
ent class and to indicate that a method is final and cannot be overridden.
REVIEW QUESTIONS
Sections 11.2–11.5
11.1 What is the printout of running the class C in (a)? What problem arises in compil-
ing the program in (b)?
class A { class A {
public A() { public A(int x) {
System.out.println( }
"A's no-arg constructor is invoked");
} }
} class B extends A {
public B() {
class B extends A { }
}
}
public class C {
public static void main(String[] args) { public class C {
B b = new B(); public static void main(String[] args) {
} B b = new B();
}
}
}
(a)
(b)
11.2 True or false?
11.3
1. A subclass is a subset of a superclass.
2. When invoking a constructor from a subclass, its superclass’s no-arg construc-
tor is always invoked.
3. You can override a private method defined in a superclass.
4. You can override a static method defined in a superclass.
Identify the problems in the following classes:
1 public class Circle {
2 private double radius;
3
4 public Circle(double radius) {
5 radius = radius;
6}
7
8 public double getRadius() {
9 return radius;
10 }
11
12 public double getArea() {
13 return radius * radius * Math.PI;
14 }
Review Questions 399
15 }
16
17 class B extends Circle {
18 private double length;
19
20 B(double radius, double length) {
21 Circle(radius);
22 length = length;
23 }
24
25 /** Override getArea() */
26 public double getArea() {
27 return getArea() * length;
28 }
29 }
11.4 How do you explicitly invoke a superclass’s constructor from a subclass?
11.5
11.6 How do you invoke an overridden superclass method from a subclass?
11.7
Explain the difference between method overloading and method overriding.
11.8
If a method in a subclass has the same signature as a method in its superclass with
11.9 the same return type, is the method overridden or overloaded?
If a method in a subclass has the same signature as a method in its superclass with
a different return type, will this be a problem?
If a method in a subclass has the same name as a method in its superclass with dif-
ferent parameter types, is the method overridden or overloaded?
Sections 11.6–11.9
11.10 Does every class have a toString method and an equals method? Where do
they come from? How are they used? Is it appropriate to override these methods?
11.11 Show the output of following program:
1 public class Test {
2 public static void main(String[] args) {
3 A a = new A(3);
4}
5}
6
7 class A extends B {
8 public A(int t) {
9 System.out.println("A's constructor is invoked");
10 }
11 }
12
13 class B {
14 public B() {
15 System.out.println("B's constructor is invoked");
16 }
17 }
Is the no-arg constructor of Object invoked when new A(3) is invoked?
11.12 For the GeometricObject and Circle classes in Listings 11.1 and 11.2, answer
the following questions:
(a) Are the following Boolean expressions true or false?
Circle circle = new Circle(1);
GeometricObject object1 = new GeometricObject();
400 Chapter 11 Inheritance and Polymorphism
(circle instanceof GeometricObject)
(object1 instanceof GeometricObject)
(circle instanceof Circle)
(object1 instanceof Circle)
(b) Can the following statements be compiled?
Circle circle = new Circle(5);
GeometricObject object = circle;
(c) Can the following statements be compiled?
GeometricObject object = new GeometricObject();
Circle circle = (Circle)object;
11.13 Suppose that Fruit, Apple, Orange, GoldenDelicious, and Macintosh are
declared, as shown in Figure 11.6.
Fruit
Apple Orange
GoldenDelicious Macintosh
FIGURE 11.6 GoldenDelicious and Macintosh are subclasses of Apple; Apple and
Orange are subclasses of Fruit.
Assume that the following declaration is given:
Fruit fruit = new GoldenDelicious();
Orange orange = new Orange();
Answer the following questions:
(1) Is fruit instanceof Fruit?
(2) Is fruit instanceof Orange?
(3) Is fruit instanceof Apple?
(4) Is fruit instanceof GoldenDelicious?
(5) Is fruit instanceof Macintosh?
(6) Is orange instanceof Orange?
(7) Is orange instanceof Fruit?
(8) Is orange instanceof Apple?
(9) Suppose the method makeApple Cider is defined in the Apple class. Can
fruit invoke this method? Can orange invoke this method?
(10) Suppose the method makeOrangeJuice is defined in the Orange class. Can
orange invoke this method? Can fruit invoke this method?
(11) Is the statement Orange p = new Apple() legal?
(12) Is the statement Macintosh p = new Apple() legal?
(13) Is the statement Apple p = new Macintosh() legal?
Review Questions 401
11.14 What is wrong in the following code?
1 public class Test {
2 public static void main(String[] args) {
3 Object fruit = new Fruit();
4 Object apple = (Apple)fruit;
5}
6}
7
8 class Apple extends Fruit {
9}
10
11 class Fruit {
12 }
Section 11.10
11.15 When overriding the equals method, a common mistake is mistyping its signa-
ture in the subclass. For example, the equals method is incorrectly written as
equals(Circle circle), as shown in (a) in the code below; instead, it should
be equals(Object circle), as shown in (b). Show the output of running class
Test with the Circle class in (a) and in (b), respectively.
public class Test {
public static void main(String[] args) {
Object circle1 = new Circle();
Object circle2 = new Circle();
System.out.println(circle1.equals(circle2));
}
}
class Circle { class Circle {
double radius; double radius;
public boolean equals(Circle circle ) { public boolean equals(Object circle ) {
return this.radius == circle.radius; return this.radius ==
((Circle)circle).radius;
}
} }
}
(a)
(b)
Sections 11.11–11.12
11.16 How do you create an ArrayList? How do you append an object to a list? How
do you insert an object at the beginning of a list? How do you find the number of
objects in a list? How do you remove a given object from a list? How do you
remove the last object from the list? How do you check whether a given object is
in a list? How do you retrieve an object at a specified index from a list?
11.17 There are three errors in the code below. Identify them.
ArrayList list = new ArrayList();
list.add("Denver");
list.add("Austin");
list.add(new java.util.Date());
String city = list.get(0);
list.set(3, "Dallas");
System.out.println(list.get(3));
402 Chapter 11 Inheritance and Polymorphism
Sections 11.13–11.14
11.18 What modifier should you use on a class so that a class in the same package can
access it, but a class in a different package cannot access it?
11.19 What modifier should you use so that a class in a different package cannot access
the class, but its subclasses in any package can access it?
11.20 In the code below, classes A and B are in the same package. If the question marks
are replaced by blanks, can class B be compiled? If the question marks are
replaced by private, can class B be compiled? If the question marks are replaced
by protected, can class B be compiled?
package p1; package p1;
public class A { public class B extends A {
? int i; public void m1(String[] args) {
System.out.println(i);
? void m() { m();
... }
}
} }
(a) (b)
11.21 In the code below, classes A and B are in different packages. If the question marks
are replaced by blanks, can class B be compiled? If the question marks are
replaced by private, can class B be compiled? If the question marks are replaced
by protected, can class B be compiled?
package p1; package p2;
public class A { public class B extends A {
? int i; public void m1(String[] args) {
? void m() { System.out.println(i);
... m();
}
}
} }
(a) (b)
11.22 How do you prevent a class from being extended? How do you prevent a method
from being overridden?
Comprehensive
11.23 Define the following terms: inheritance, superclass, subclass, the keywords super
and this, casting objects, the modifiers protected and final.
11.24 Indicate true or false for the following statements:
■ A protected datum or method can be accessed by any class in the same package.
■ A protected datum or method can be accessed by any class in different
packages.
■ A protected datum or method can be accessed by its subclasses in any package.
■ A final class can have instances.
■ A final class can be extended.
■ A final method can be overridden.
■ You can always successfully cast an instance of a subclass to a superclass.
■ You can always successfully cast an instance of a superclass to a subclass.
Programming Exercises 403
11.25 Describe the difference between method matching and method binding.
11.26 What is polymorphism? What is dynamic binding?
PROGRAMMING EXERCISES
Sections 11.2–11.4
11.1 (The Triangle class) Design a class named Triangle that extends
GeometricObject. The class contains:
■ Three double data fields named side1, side2, and side3 with default values
1.0 to denote three sides of the triangle.
■ A no-arg constructor that creates a default triangle.
■ A constructor that creates a triangle with the specified side1, side2, and
side3.
■ The accessor methods for all three data fields.
■ A method named getArea() that returns the area of this triangle.
■ A method named getPerimeter() that returns the perimeter of this triangle.
■ A method named toString() that returns a string description for the triangle.
For the formula to compute the area of a triangle, see Exercise 2.21. The toString()
method is implemented as follows:
return "Triangle: side1 = " + side1 + " side2 = " + side2 +
" side3 = " + side3;
Draw the UML diagram for the classes Triangle and GeometricObject.
Implement the class. Write a test program that creates a Triangle object with
sides 1, 1.5, 1, color yellow and filled true, and displays the area,
perimeter, color, and whether filled or not.
Sections 11.5–11.11
11.2 (The Person, Student, Employee, Faculty, and Staff classes) Design a
class named Person and its two subclasses named Student and Employee.
Make Faculty and Staff subclasses of Employee. A person has a name,
address, phone number, and email address. A student has a class status (freshman,
sophomore, junior, or senior). Define the status as a constant. An employee has an
office, salary, and date hired. Define a class named MyDate that contains the fields
year, month, and day. A faculty member has office hours and a rank. A staff
member has a title. Override the toString method in each class to display the
class name and the person’s name.
Draw the UML diagram for the classes. Implement the classes. Write a test pro-
gram that creates a Person, Student, Employee, Faculty, and Staff, and
invokes their toString() methods.
11.3 (Subclasses of Account) In Exercise 8.7, the Account class was defined to model
a bank account. An account has the properties account number, balance, annual
interest rate, and date created, and methods to deposit and withdraw funds. Create
two subclasses for checking and saving accounts. A checking account has an over-
draft limit, but a savings account cannot be overdrawn.
Draw the UML diagram for the classes. Implement the classes. Write a test pro-
gram that creates objects of Account, SavingsAccount, and CheckingAccount
and invokes their toString() methods.
404 Chapter 11 Inheritance and Polymorphism
11.4 (Implementing MyStack using inheritance) In Listing 11.9, MyStack is imple-
mented using composition. Create a new stack class that extends ArrayList.
Draw the UML diagram for the classes. Implement MyStack. Write a test pro-
gram that prompts the user to enter five strings and displays them in reverse order.
11.5 (The Course class) Rewrite the Course class in Listing 10.6. Use an
ArrayList to replace an array to store students. You should not change the
original contract of the Course class (i.e., the definition of the constructors and
methods should not be changed).
11.6 (Using ArrayList) Write a program that creates an ArrayList and adds a
Loan object, a Date object, a string, a JFrame object, and a Circle object to
the list, and use a loop to display all the elements in the list by invoking the
object’s toString() method.
11.7*** (Implementing ArrayList) ArrayList is implemented in the Java API.
Implement ArrayList and the methods defined in Figure 11.3. (Hint: Use an
array to store the elements in ArrayList. If the size of the ArrayList exceeds
the capacity of the current array, create a new array that doubles the size of the
current array and copy the contents of the current to the new array.)
11.8** (New Account class) An Account class was specified in Exercise 8.7. Design
a new Account class as follows:
■ Add a new data field name of the String type to store the name of the customer.
■ Add a new constructor that constructs an account with the specified name,
id, and balance.
■ Add a new data field named transactions whose type is ArrayList that
stores the transaction for the accounts. Each transaction is an instance of the
Transaction class. The Transaction class is defined as shown in Figure 11.7.
■ Modify the withdraw and deposit methods to add a transaction to the
transactions array list.
■ All other properties and methods are same as in Exercise 8.7.
Write a test program that creates an Account with annual interest rate 1.5%,
balance 1000, id 1122, and name George. Deposit $30, $40, $50 to the account
and withdraw $5, $4, $2 from the account. Print an account summary that shows
account holder name, interest rate, balance, and all transactions.
Transaction The get and set methods for these data fields are
provided in the class but omitted in the UML diagram
-date: java.util.Date for brevity.
-type: char
The date of this transaction.
-amount: double The type of the transaction, such as 'W' for withdrawal, 'D'
-balance: double for deposit.
-description: String The amount of the transaction.
The new balance after this transaction.
+Transaction(type: char, The description of this transaction.
amount: double, balance:
double, description: String) Construct a Transaction with the specified date, type,
balance, and description.
FIGURE 11.7 The Transaction class describes a transaction for a bank account.
CHAPTER 12
GUI BASICS
Objectives
■ To distinguish between Swing and AWT (§12.2).
■ To describe the Java GUI API hierarchy (§12.3).
■ To create user interfaces using frames, panels, and simple GUI components (§12.4).
■ To understand the role of layout managers (§12.5).
■ To use the FlowLayout, GridLayout, and BorderLayout managers
to lay out components in a container (§12.5).
■ To use JPanel to make panels as subcontainers (§12.6).
■ To specify colors and fonts using the Color and Font
classes (§§12.7–12.8).
■ To apply common features such as borders, tool tips,
fonts, and colors on Swing components (§12.9).
■ To use borders to visually group user-interface
components (§12.9).
■ To create image icons using the ImageIcon class (§12.10).
406 Chapter 12 GUI Basics
12.1 Introduction
The design of the API for Java GUI programming is an excellent example of how the object-
oriented principle is applied. This chapter serves two purposes. First, it introduces the basics
of Java GUI programming. Second, it uses GUI to demonstrate OOP. Specifically, this chap-
ter will introduce the framework of Java GUI API and discuss GUI components and their rela-
tionships, containers and layout managers, colors, fonts, borders, image icons, and tool tips.
Swing components 12.2 Swing vs. AWT
lightweight We used simple GUI examples to demonstrate OOP in §8.6.3, “Displaying GUI Components.”
heavyweight We used the GUI components such as JButton, JLabel, JTextField, JRadioButton, and
why prefix J? JComboBox. Why do the GUI component classes have the prefix J? Instead of JButton, why
not name it simply Button? In fact, there is a class already named Button in the java.awt
package.
When Java was introduced, the GUI classes were bundled in a library known as the Abstract
Windows Toolkit (AWT). AWT is fine for developing simple graphical user interfaces, but not for
developing comprehensive GUI projects. Besides, AWT is prone to platform-specific bugs. The
AWT user-interface components were replaced by a more robust, versatile, and flexible library
known as Swing components. Swing components are painted directly on canvases using Java
code, except for components that are subclasses of java.awt.Window or java.awt.Panel,
which must be drawn using native GUI on a specific platform. Swing components depend less on
the target platform and use less of the native GUI resource. For this reason, Swing components
that don’t rely on native GUI are referred to as lightweight components, and AWT components
are referred to as heavyweight components.
To distinguish new Swing component classes from their AWT counterparts, the Swing
GUI component classes are named with a prefixed J. Although AWT components are still
supported in Java, it is better to learn to how program using Swing components, because the
AWT user-interface components will eventually fade away. This book uses Swing GUI com-
ponents exclusively.
12.3 The Java GUI API
The GUI API contains classes that can be classified into three groups: component classes, con-
tainer classes, and helper classes. Their hierarchical relationships are shown in Figure 12.1.
The component classes, such as JButton, JLabel, and JTextField, are for creating the
user interface. The container classes, such as JFrame, JPanel, and JApplet, are used to
contain other components. The helper classes, such as Graphics, Color, Font,
FontMetrics, and Dimension, are used to support GUI components.
Note
The JFrame, JApplet, JDialog, and JComponent classes and their subclasses are grouped
in the javax.swing package. All the other classes in Figure 12.1 are grouped in the java.awt
package.
12.3.1 Component Classes
An instance of Component can be displayed on the screen. Component is the root class of all
the user-interface classes including container classes, and JComponent is the root class of all
the lightweight Swing components. Both Component and JComponent are abstract classes.
Abstract classes will be introduced in Chapter 14, “Abstract Classes and Interfaces.” For now,
all you need to know is that abstract classes are same as classes except that you cannot create
instances using the new operator. For example, you cannot use new JComponent() to create an
12.3 The Java GUI API 407
Dimension LayoutManager Classes in the java.awt Heavyweight
Font 1 package
JApplet
FontMetrics JFrame
JDialog
Object Color Panel Applet
Graphics
Component Container Window Frame
* Dialog
JComponent Swing GUI
Lightweight
components such as
JButton, JLabel, Swing Components
JTextField, JPanel, in the javax.swing
etc.
package
FIGURE 12.1 Java GUI programming utilizes the classes shown in this hierarchical diagram.
instance of JComponent. However, you can use the constructors of concrete subclasses of
JComponent to create JComponent instances. It is important to become familiar with the
class inheritance hierarchy. For example, the following statements all display true:
JButton jbtOK = new JButton("OK");
System.out.println(jbtOK instanceof JButton);
System.out.println(jbtOK instanceof JComponent);
System.out.println(jbtOK instanceof Container);
System.out.println(jbtOK instanceof Component);
System.out.println(jbtOK instanceof Object);
12.3.2 Container Classes
An instance of Container can hold instances of Component. Container classes are GUI com-
ponents that are used to contain other GUI components. Window, Panel, Applet, Frame, and
Dialog are the container classes for AWT components. To work with Swing components, use
Container, JFrame, JDialog, JApplet, and JPanel, as described in Table 12.1.
TABLE 12.1 GUI Container Classes
Container Class Description
java.awt.Container is used to group components. Frames, panels, and applets are its subclasses.
javax.swing.JFrame
is a window not contained inside another window. It is used to hold other Swing
javax.swing.JPanel user-interface components in Java GUI applications.
javax.swing.JApplet is an invisible container that holds user-interface components. Panels can be nested. You can place panels
javax.swing.JDialog inside a container that includes a panel. JPanel is also often used as a canvas to draw graphics.
is a subclass of Applet. You must extend JApplet to create a Swing-based Java applet.
is a popup window or message box generally used as a temporary window to receive additional informa-
tion from the user or to provide notification that an event has occurred.
408 Chapter 12 GUI Basics
12.3.3 GUI Helper Classes
The helper classes, such as Graphics, Color, Font, FontMetrics, Dimension, and
LayoutManager, are not subclasses of Component. They are used to describe the properties
of GUI components, such as graphics context, colors, fonts, and dimension, as described in
Table 12.2.
TABLE 12.2 GUI Helper Classes
Helper Class Description
java.awt.Graphics is an abstract class that provides the methods for drawing strings,
java.awt.Color lines, and simple shapes.
java.awt.Font deals with the colors of GUI components. For example, you can spec-
ify background or foreground colors in components like JFrame and
java.awt.FontMetrics JPanel, or you can specify colors of lines, shapes, and strings in
java.awt.Dimension drawings.
java.awt.LayoutManager
specifies fonts for the text and drawings on GUI components.
For example, you can specify the font type (e.g., SansSerif), style
(e.g., bold), and size (e.g., 24 points) for the text on a button.
is an abstract class used to get the properties of the fonts.
encapsulates the width and height of a component (in integer
precision) in a single object.
specifies how components are arranged in a container.
import package Note
create frame The helper classes are in the java.awt package. The Swing components do not replace all the
set size classes in AWT, only the AWT GUI component classes (e.g., Button, TextField, TextArea).
center frame The AWT helper classes are still useful in GUI programming.
close upon exit
display the frame 12.4 Frames
To create a user interface, you need to create either a frame or an applet to hold the user-inter-
face components. Creating Java applets will be introduced in Chapter 18, “Applets and Multi-
media.” This section introduces frames.
12.4.1 Creating a Frame
To create a frame, use the JFrame class, as shown in Figure 12.2.
The program in Listing 12.1 creates a frame:
LISTING 12.1 MyFrame.java
1 import javax.swing.JFrame;
2
3 public class MyFrame {
4 public static void main(String[] args) {
5 JFrame frame = new JFrame("MyFrame"); // Create a frame
6 frame.setSize(400, 300); // Set the frame size
7 frame.setLocationRelativeTo(null); // Center a frame
8 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
9 frame.setVisible(true); // Display the frame
10 }
11 }
12.4 Frames 409
javax.swing.JFrame Creates a default frame with no title.
Creates a frame with the specified title.
+JFrame()
+JFrame(title: String) Sets the size of the frame.
+setSize(width: int, height: int): void
+setLocation(x: int, y: int): void Sets the upper-left-corner location of the frame.
+setVisible(visible: boolean): void Sets true to display the frame.
+setDefaultCloseOperation(mode: int): void Specifies the operation when the frame is closed.
+setLocationRelativeTo(c: Component): Sets the location of the frame relative to the specified component.
void If the component is null, the frame is centered on the screen.
+pack(): void Automatically sets the frame size to hold the components in the
frame.
FIGURE 12.2 JFrame is a top-level container to hold GUI components.
The frame is not displayed until the frame.setVisible(true) method is invoked.
frame.setSize(400, 300) specifies that the frame is 400 pixels wide and 300 pixels
high. If the setSize method is not used, the frame will be sized to display just the title bar.
Since the setSize and setVisible methods are both defined in the Component class, they
are inherited by the JFrame class. Later you will see that these methods are also useful in
many other subclasses of Component.
When you run the MyFrame program, a window will be displayed on the screen (see
Figure 12.3(a)).
Title bar Title bar
Content Content
pane pane
(a) (b)
FIGURE 12.3 (a) The program creates and displays a frame with the title MyFrame. (b) An OK button is added to the
frame.
Invoking setLocationRelativeTo(null) (line 7) centers the frame on the screen.
Invoking setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) (line 8) tells the pro-
gram to terminate when the frame is closed. If this statement is not used, the program does not
terminate when the frame is closed. In that case, you have to stop the program by pressing
Ctrl+C at the DOS prompt window in Windows or stop the process by using the kill com-
mand in Unix. If you run the program from an IDE such as Eclipse or NetBeans, you need to
click the red Terminate button in the Console pane to stop the program.
Note pixel and resolution
Recall that a pixel is the smallest unit of space available for drawing on the screen. You can think
of a pixel as a small rectangle and think of the screen as paved with pixels. The resolution speci-
fies the number of pixels per square inch. The more pixels the screen has, the higher the screen’s
resolution. The higher the resolution, the finer the detail you can see.
Note setSize before centering
You should invoke the setSize(w, h) method before invoking setLocationRelativeTo-
(null) to center the frame.
410 Chapter 12 GUI Basics
create a button 12.4.2 Adding Components to a Frame
add to frame
set size The frame shown in Figure 12.3(a) is empty. Using the add method, you can add components
exit upon closing window into the frame, as in Listing 12.2.
center the frame
set visible LISTING 12.2 MyFrameWithComponents.java
content-pane delegation 1 import javax.swing.*;
2
3 public class MyFrameWithComponents {
4 public static void main(String[] args) {
5 JFrame frame = new JFrame("MyFrameWithComponents");
6
7 // Add a button into the frame
8 JButton jbtOK = new JButton("OK");
9 frame.add(jbtOK);
10
11 frame.setSize(400, 300);
12 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
13 frame.setLocationRelativeTo(null); // Center the frame
14 frame.setVisible(true);
15 }
16 }
Each JFrame contains a content pane. A content pane is an instance of java.awt.Container.
The GUI components such as buttons are placed in the content pane in a frame. In earlier version
of Java, you had to use the getContentPane method in the JFrame class to return the content
pane of the frame, then invoke the content pane’s add method to place a component into the con-
tent pane, as follows:
java.awt.Container container = frame.getContentPane();
container.add(jbtOK);
This was cumbersome. The new version of Java since Java 5 allows you to place components
into the content pane by invoking a frame’s add method, as follows:
frame.add(jbtOK);
This new feature is called content-pane delegation. Strictly speaking, a component is added
into the content pane of a frame. For simplicity we say that a component is added to a
frame.
An object of JButton was created using new JButton("OK"), and this object was added
to the content pane of the frame (line 9).
The add(Component comp) method defined in the Container class adds an instance of
Component to the container. Since JButton is a subclass of Component, an instance of
JButton is also an instance of Component. To remove a component from a container, use the
remove method. The following statement removes the button from the container:
container.remove(jbtOK);
When you run the program MyFrameWithComponents, the window will be displayed as in
Figure 12.3(b). The button is always centered in the frame and occupies the entire frame no
matter how you resize it. This is because components are put in the frame by the content
pane’s layout manager, and the default layout manager for the content pane places the button
in the center. In the next section, you will use several different layout managers to place com-
ponents in the desired locations.
12.5 Layout Managers 411
12.5 Layout Managers
In many other window systems, the user-interface components are arranged by using hard-
coded pixel measurements. For example, put a button at location (10, 10) in the window.
Using hard-coded pixel measurements, the user interface might look fine on one system but
be unusable on another. Java’s layout managers provide a level of abstraction that automati-
cally maps your user interface on all window systems.
The Java GUI components are placed in containers, where they are arranged by the con-
tainer’s layout manager. In the preceding program, you did not specify where to place the OK
button in the frame, but Java knows where to place it, because the layout manager works
behind the scenes to place components in the correct locations. A layout manager is created
using a layout manager class.
Layout managers are set in containers using the setLayout(aLayoutManager) method.
For example, you can use the following statements to create an instance of XLayout and set
it in a container:
LayoutManager layoutManager = new XLayout();
container.setLayout(layoutManager);
This section introduces three basic layout managers: FlowLayout, GridLayout, and Bord-
erLayout.
12.5.1 FlowLayout Video Note
Use FlowLayout
FlowLayout is the simplest layout manager. The components are arranged in the container from
left to right in the order in which they were added. When one row is filled, a new row is started.
You can specify the way the components are aligned by using one of three constants: FlowLay-
out.RIGHT, FlowLayout.CENTER, or FlowLayout.LEFT. You can also specify the gap
between components in pixels. The class diagram for FlowLayout is shown in Figure 12.4.
java.awt.FlowLayout The get and set methods for these data
fields are provided in the class, but
-alignment: int omitted in the UML diagram for brevity.
-hgap: int
-vgap: int The alignment of this layout manager (default: CENTER).
The horizontal gap of this layout manager (default: 5 pixels).
+FlowLayout() The vertical gap of this layout manager (default: 5 pixels).
+FlowLayout(alignment: int)
+FlowLayout(alignment: int, hgap: Creates a default FlowLayout manager.
Creates a FlowLayout manager with a specified alignment.
int, vgap: int) Creates a FlowLayout manager with a specified alignment,
horizontal gap, and vertical gap.
FIGURE 12.4 FlowLayout lays out components row by row.
Listing 12.3 gives a program that demonstrates flow layout. The program adds three labels
and text fields into the frame with a FlowLayout manager, as shown in Figure 12.5.
LISTING 12.3 ShowFlowLayout.java
1 import javax.swing.JLabel;
2 import javax.swing.JTextField;
3 import javax.swing.JFrame;
412 Chapter 12 GUI Basics
extends JFrame 4 import java.awt.FlowLayout;
set layout 5
add label 6 public class ShowFlowLayout extends JFrame {
add text field 7 public ShowFlowLayout() {
8 // Set FlowLayout, aligned left with horizontal gap 10
create frame 9 // and vertical gap 20 between components
set visible 10 setLayout(new FlowLayout(FlowLayout.LEFT, 10, 20));
11
12 // Add labels and text fields to the frame
13 add(new JLabel("First Name"));
14 add(new JTextField(8));
15 add(new JLabel("MI"));
16 add(new JTextField(1));
17 add(new JLabel("Last Name"));
18 add(new JTextField(8));
19 }
20
21 /** Main method */
22 public static void main(String[] args) {
23 ShowFlowLayout frame = new ShowFlowLayout();
24 frame.setTitle("ShowFlowLayout");
25 frame.setSize(200, 200);
26 frame.setLocationRelativeTo(null); // Center the frame
27 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
28 frame.setVisible(true);
29 }
30 }
(a) (b)
FIGURE 12.5 The components are added by the FlowLayout manager to fill in the rows in
the container one after another.
This example creates a program using a style different from the programs in the preceding sec-
tion, where frames were created using the JFrame class. This example creates a class named
ShowFlowLayout that extends the JFrame class (line 6). The main method in this program
creates an instance of ShowFlowLayout (line 23). The constructor of ShowFlowLayout con-
structs and places the components in the frame. This is the preferred style of creating GUI
applications—for three reasons:
■ Creating a GUI application means creating a frame, so it is natural to define a frame
to extend JFrame.
■ The frame may be further extended to add new components or functions.
■ The class can be easily reused. For example, you can create multiple frames by
creating multiple instances of the class.
Using one style consistently makes programs easy to read. From now on, most of the GUI main
classes will extend the JFrame class. The constructor of the main class constructs the user inter-
face. The main method creates an instance of the main class and then displays the frame.
12.5 Layout Managers 413
In this example, the FlowLayout manager is used to place components in a frame. If you
resize the frame, the components are automatically rearranged to fit. In Figure 12.5(a), the
first row has three components, but in Figure 12.5(a), the first row has four components,
because the width has been increased.
If you replace the setLayout statement (line 10) with setLayout(new FlowLayout-
(FlowLayout.RIGHT, 0, 0)), all the rows of buttons will be right aligned with no gaps.
An anonymous FlowLayout object was created in the statement (line 10):
setLayout(new FlowLayout(FlowLayout.LEFT, 10, 20));
which is equivalent to:
FlowLayout layout = new FlowLayout(FlowLayout.LEFT, 10, 20);
setLayout(layout);
This code creates an explicit reference to the object layout of the FlowLayout class. The
explicit reference is not necessary, because the object is not directly referenced in the
ShowFlowLayout class.
Suppose you add the same button into the frame ten times; will ten buttons appear in the
frame? No, a GUI component such as a button can be added into only one container and only
once in a container. Adding a button into a container multiple times is the same as adding it once.
Caution
Do not forget to put the new operator before a layout manager class when setting a layout style—
for example, setLayout(new FlowLayout()).
Note
The constructor ShowFlowLayout() does not explicitly invoke the constructor JFrame(),
but the constructor JFrame() is invoked implicitly. See §11.3.2, “Constructor Chaining.”
12.5.2 GridLayout
The GridLayout manager arranges components in a grid (matrix) formation. The compo-
nents are placed in the grid from left to right, starting with the first row, then the second, and
so on, in the order in which they are added. The class diagram for GridLayout is shown in
Figure 12.6.
java.awt.GridLayout The get and set methods for these data
fields are provided in the class, but
-rows: int omitted in the UML diagram for brevity.
-columns: int
-hgap: int The number of rows in this layout manager (default: 1).
-vgap: int The number of columns in this layout manager (default: 1).
The horizontal gap of this layout manager (default: 0).
+GridLayout() The vertical gap of this layout manager (default: 0).
+GridLayout(rows: int, columns: int)
+GridLayout(rows: int, columns: int, Creates a default GridLayout manager.
Creates a GridLayout with a specified number of rows and columns.
hgap: int, vgap: int) Creates a GridLayout manager with a specified number of rows and
columns, horizontal gap, and vertical gap.
FIGURE 12.6 GridLayout lays out components in equal-sized cells on a grid.
414 Chapter 12 GUI Basics
set layout You can specify the number of rows and columns in the grid. The basic rule is as follows:
add label
add text field ■ The number of rows or the number of columns can be zero, but not both. If one is
zero and the other is nonzero, the nonzero dimension is fixed, while the zero dimen-
create a frame sion is determined dynamically by the layout manager. For example, if you specify
set visible zero rows and three columns for a grid that has ten components, GridLayout cre-
ates three fixed columns of four rows, with the last row containing one component. If
you specify three rows and zero columns for a grid that has ten components,
GridLayout creates three fixed rows of four columns, with the last row containing
two components.
■ If both the number of rows and the number of columns are nonzero, the number of
rows is the dominating parameter; that is, the number of rows is fixed, and the layout
manager dynamically calculates the number of columns. For example, if you specify
three rows and three columns for a grid that has ten components, GridLayout cre-
ates three fixed rows of four columns, with the last row containing two components.
Listing 12.4 gives a program that demonstrates grid layout. The program is similar to the one
in Listing 12.3. It adds three labels and three text fields to the frame of GridLayout instead
of FlowLayout, as shown in Figure 12.7.
LISTING 12.4 ShowGridLayout.java
1 import javax.swing.JLabel;
2 import javax.swing.JTextField;
3 import javax.swing.JFrame;
4 import java.awt.GridLayout;
5
6 public class ShowGridLayout extends JFrame {
7 public ShowGridLayout() {
8 // Set GridLayout, 3 rows, 2 columns, and gaps 5 between
9 // components horizontally and vertically
10 setLayout(new GridLayout(3, 2, 5, 5));
11
12 // Add labels and text fields to the frame
13 add(new JLabel("First Name"));
14 add(new JTextField(8));
15 add(new JLabel("MI"));
16 add(new JTextField(1));
17 add(new JLabel("Last Name"));
18 add(new JTextField(8));
19 }
20
21 /** Main method */
22 public static void main(String[] args) {
23 ShowGridLayout frame = new ShowGridLayout();
24 frame.setTitle("ShowGridLayout");
25 frame.setSize(200, 125);
26 frame.setLocationRelativeTo(null); // Center the frame
27 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
28 frame.setVisible(true);
29 }
30 }
If you resize the frame, the layout of the buttons remains unchanged (i.e., the number of rows
and columns does not change, and the gaps don’t change either).
All components are given equal size in the container of GridLayout.
12.5 Layout Managers 415
FIGURE 12.7 The GridLayout manager divides the container into grids; then the compo-
nents are added to fill in the cells row by row.
Replacing the setLayout statement (line 10) with setLayout(new GridLayout(3,
10)) would still yield three rows and two columns. The columns parameter is ignored
because the rows parameter is nonzero. The actual number of columns is calculated by the
layout manager.
What would happen if the setLayout statement (line 10) were replaced with setLay-
out(new GridLayout(4, 2)) or with setLayout(new GridLayout(2, 2))? Please
try it yourself.
Note
In FlowLayout and GridLayout, the order in which the components are added to the con-
tainer is important. It determines the location of the components in the container.
12.5.3 BorderLayout
The BorderLayout manager divides a container into five areas: East, South, West, North,
and Center. Components are added to a BorderLayout by using add(Component,
index), where index is a constant BorderLayout.EAST, BorderLayout.SOUTH,
BorderLayout.WEST, BorderLayout.NORTH, or BorderLayout.CENTER. The class dia-
gram for BorderLayout is shown in Figure 12.8.
java.awt.BorderLayout The get and set methods for these data
fields are provided in the class, but
-hgap: int omitted in the UML diagram for brevity.
-vgap: int
The horizontal gap of this layout manager (default: 0).
+BorderLayout() The vertical gap of this layout manager (default: 0).
+BorderLayout(hgap: int, vgap: int)
Creates a default BorderLayout manager.
Creates a BorderLayout manager with a specified number of
horizontal gap, and vertical gap.
FIGURE 12.8 BorderLayout lays out components in five areas.
The components are laid out according to their preferred sizes and their placement in the
container. The North and South components can stretch horizontally; the East and West com-
ponents can stretch vertically; the Center component can stretch both horizontally and verti-
cally to fill any empty space.
Listing 12.5 gives a program that demonstrates border layout. The program adds five but-
tons labeled East, South, West, North, and Center into the frame with a BorderLayout
manager, as shown in Figure 12.9.
416 Chapter 12 GUI Basics
set layout LISTING 12.5 ShowBorderLayout.java
add buttons
1 import javax.swing.JButton;
create a frame 2 import javax.swing.JFrame;
set visible 3 import java.awt.BorderLayout;
4
5 public class ShowBorderLayout extends JFrame {
6 public ShowBorderLayout() {
7 // Set BorderLayout with horizontal gap 5 and vertical gap 10
8 setLayout(new BorderLayout(5, 10));
9
10 // Add buttons to the frame
11 add(new JButton("East"), BorderLayout.EAST);
12 add(new JButton("South"), BorderLayout.SOUTH);
13 add(new JButton("West"), BorderLayout.WEST);
14 add(new JButton("North"), BorderLayout.NORTH);
15 add(new JButton("Center"), BorderLayout.CENTER);
16 }
17
18 /** Main method */
19 public static void main(String[] args) {
20 ShowBorderLayout frame = new ShowBorderLayout();
21 frame.setTitle("ShowBorderLayout");
22 frame.setSize(300, 200);
23 frame.setLocationRelativeTo(null); // Center the frame
24 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
25 frame.setVisible(true);
26 }
27 }
FIGURE 12.9 BorderLayout divides the container into five areas, each of which can hold a
component.
The buttons are added to the frame (lines 11–15). Note that the add method for BorderLayout
is different from the one for FlowLayout and GridLayout. With BorderLayout you specify
where to put the components.
It is unnecessary to place components to occupy all the areas. If you remove the East but-
ton from the program and rerun it, you will see that the center stretches rightward to occupy
the East area.
Note
BorderLayout interprets the absence of an index specification as BorderLayout.CENTER.
For example, add(component) is the same as add(Component, BorderLayout.CEN-
TER). If you add two components into a container of BorderLayout, as follows,
container.add(component1);
container.add(component2);
only the last component is displayed.
12.6 Using Panels as Subcontainers 417
12.5.4 Properties of Layout Managers
Layout managers have properties that can be changed dynamically. FlowLayout has
alignment, hgap, and vgap properties. You can use the setAlignment, setHgap, and
setVgap methods to specify the alignment and the horizontal and vertical gaps. GridLayout
has the rows, columns, hgap, and vgap properties. You can use the setRows, setColumns,
setHgap, and setVgap methods to specify the number of rows, the number of columns, and
the horizontal and vertical gaps. BorderLayout has the hgap and vgap properties. You can
use the setHgap and setVgap methods to specify the horizontal and vertical gaps.
In the preceding sections an anonymous layout manager is used because the properties of a
layout manager do not change, once it is created. If you have to change the properties of a lay-
out manager dynamically, the layout manager must be explicitly referenced by a variable. You
can then change the properties of the layout manager through the variable. For example, the
following code creates a layout manager and sets its properties:
// Create a layout manager
FlowLayout flowLayout = new FlowLayout();
// Set layout properties
flowLayout.setAlignment(FlowLayout.RIGHT);
flowLayout.setHgap(10);
flowLayout.setVgap(20);
12.6 Using Panels as Subcontainers Video Note
Use panels as subcontainers
Suppose that you want to place ten buttons and a text field in a frame. The buttons are placed in
grid formation, but the text field is placed on a separate row. It is difficult to achieve the desired
look by placing all the components in a single container. With Java GUI programming, you can
divide a window into panels. Panels act as subcontainers to group user-interface components.
You add the buttons in one panel, then add the panel into the frame.
The Swing version of panel is JPanel. You can use new JPanel() to create a panel with
a default FlowLayout manager or new JPanel(LayoutManager) to create a panel with
the specified layout manager. Use the add(Component) method to add a component to the
panel. For example, the following code creates a panel and adds a button to it:
JPanel p = new JPanel();
p.add(new JButton("OK"));
Panels can be placed inside a frame or inside another panel. The following statement places
panel p into frame f:
f.add(p);
Listing 12.6 gives an example that demonstrates using panels as subcontainers. The program
creates a user interface for a microwave oven, as shown in Figure 12.10.
LISTING 12.6 TestPanels.java panel p1
1 import java.awt.*;
2 import javax.swing.*;
3
4 public class TestPanels extends JFrame {
5 public TestPanels() {
6 // Create panel p1 for the buttons and set GridLayout
7 JPanel p1 = new JPanel();
8 p1.setLayout(new GridLayout(4, 3));
9
418 Chapter 12 GUI Basics
panel p2 10 // Add buttons to the panel
add p2 to frame 11 for (int i = 1; i <= 9; i++) {
12 p1.add(new JButton("" + i));
13 }
14
15 p1.add(new JButton("" + 0));
16 p1.add(new JButton("Start"));
17 p1.add(new JButton("Stop"));
18
19 // Create panel p2 to hold a text field and p1
20 JPanel p2 = new JPanel(new BorderLayout());
21 p2.add(new JTextField("Time to be displayed here"),
22 BorderLayout.NORTH);
23 p2.add(p1, BorderLayout.CENTER);
24
25 // add contents into the frame
26 add(p2, BorderLayout.EAST);
27 add(new JButton("Food to be placed here"),
28 BorderLayout.CENTER);
29 }
30
31 /** Main method */
32 public static void main(String[] args) {
33 TestPanels frame = new TestPanels();
34 frame.setTitle("The Front View of a Microwave Oven");
35 frame.setSize(400, 250);
36 frame.setLocationRelativeTo(null); // Center the frame
37 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
38 frame.setVisible(true);
39 }
40 }
Button Frame
Content panel
Panel p2
Panel p1
FIGURE 12.10 The program uses panels to organize components.
The setLayout method is defined in java.awt.Container. Since JPanel is a subclass of
Container, you can use setLayout to set a new layout manager in the panel (line 8). Lines
7–8 can be replaced by JPanel p1 = new JPanel(new GridLayout(4, 3)).
To achieve the desired layout, the program uses panel p1 of GridLayout to group the
number buttons, the Stop button, and the Start button, and panel p2 of BorderLayout to hold
a text field in the north and p1 in the center. The button representing the food is placed in the
center of the frame, and p2 is placed in the east of the frame.
The statement (lines 21–22)
p2.add(new JTextField("Time to be displayed here"),
BorderLayout.NORTH);
creates an instance of JTextField and adds it to p2. JTextField is a GUI component that
can be used for user input as well as to display values.
12.8 The Font Class 419
Note superclass Container
It is worthwhile to note that the Container class is the superclass for GUI component classes,
such as JButton. Every GUI component is a container. In theory, you could use the
setLayout method to set the layout in a button and add components into a button, because all
the public methods in the Container class are inherited into JButton, but for practical rea-
sons you should not use buttons as containers.
12.7 The Color Class
You can set colors for GUI components by using the java.awt.Color class. Colors are
made of red, green, and blue components, each represented by an int value that describes its
intensity, ranging from 0 (darkest shade) to 255 (lightest shade). This is known as the RGB
model.
You can create a color using the following constructor:
public Color(int r, int g, int b);
in which r, g, and b specify a color by its red, green, and blue components. For example,
Color color = new Color(128, 100, 100);
Note IllegalArgumentException
The arguments r, g, b are between 0 and 255. If a value beyond this range is passed to the argu-
ment, an IllegalArgumentException will occur.
You can use the setBackground(Color c) and setForeground(Color c) methods
defined in the java.awt.Component class to set a component’s background and foreground
colors. Here is an example of setting the background and foreground of a button:
JButton jbtOK = new JButton("OK");
jbtOK.setBackground(color);
jbtOK.setForeground(new Color(100, 1, 1));
Alternatively, you can use one of the 13 standard colors (BLACK, BLUE, CYAN, DARK_GRAY,
GRAY, GREEN, LIGHT_GRAY, MAGENTA, ORANGE, PINK, RED, WHITE, and YELLOW) defined as
constants in java.awt.Color. The following code, for instance, sets the foreground color of
a button to red:
jbtOK.setForeground(Color.RED);
12.8 The Font Class
You can create a font using the java.awt.Font class and set fonts for the components using
the setFont method in the Component class.
The constructor for Font is:
public Font(String name, int style, int size);
You can choose a font name from SansSerif, Serif, Monospaced, Dialog, or
DialogInput, choose a style from Font.PLAIN (0), Font.BOLD (1), Font.ITALIC (2),
and Font.BOLD + Font.ITALIC (3), and specify a font size of any positive integer. For
example, the following statements create two fonts and set one font to a button.
Font font1 = new Font("SansSerif", Font.BOLD, 16);
Font font2 = new Font("Serif", Font.BOLD + Font.ITALIC, 12);
JButton jbtOK = new JButton("OK");
jbtOK.setFont(font1);
420 Chapter 12 GUI Basics
find available fonts Tip
If your system supports other fonts, such as “Times New Roman,” you can use it to create a
Font object. To find the fonts available on your system, you need to obtain an instance of
java.awt.GraphicsEnvironment using its static method getLocalGraphicsEnvi-
ronment(). GraphicsEnvironment is an abstract class that describes the graphics environ-
ment on a particular system. You can use its getAllFonts() method to obtain all the available
fonts on the system and its getAvailableFontFamilyNames() method to obtain the
names of all the available fonts. For example, the following statements print all the available font
names in the system:
GraphicsEnvironment e =
GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontnames = e.getAvailableFontFamilyNames();
for (int i = 0; i < fontnames.length; i++)
System.out.println(fontnames[i]);
Component 12.9 Common Features of Swing GUI Components
In this chapter you have used several GUI components (e.g., JFrame, Container, JPanel,
JButton, JLabel, JTextField). Many more GUI components will be introduced in this
book. It is important to understand the common features of Swing GUI components. The
Video Note The get and set methods for these data
Use Swing common properties fields are provided in the class, but
omitted in the UML diagram for brevity.
java.awt.Component
The font of this component.
-font: java.awt.Font The background color of this component.
-background: java.awt.Color The foreground color of this component.
-foreground: java.awt.Color The preferred size of this component.
-preferredSize: java.awt.Dimension Indicates whether this component is visible.
-visible: boolean
+getWidth(): int Returns the width of this component.
+getHeight(): int Returns the height of this component.
+getX(): int getX() and getY() return the coordinate of the
+getY(): int
component’s upper-left corner within its parent component.
java.awt.Container Adds a component to the container.
Adds a component to the container with the specified index.
+add(comp: Component): Component Removes the component from the container.
+add(comp: Component, index: int): Component Returns the layout manager for this container.
+remove(comp: Component): void Sets the layout manager for this container.
+getLayout(): LayoutManager Paints each of the components in this container.
+setLayout(l: LayoutManager): void
+paintComponents(g: Graphics): void
javax.swing.JComponent The get and set methods for these data
-toolTipText: String fields are provided in the class, but
omitted in the UML diagram for brevity.
-border: javax.swing.border.Border
The tool tip text for this component. Tool tip text is displayed when
the mouse points on the component without clicking.
The border for this component.
FIGURE 12.11 All the Swing GUI components inherit the public methods from Component, Container, and JComponent.
12.9 Common Features of Swing GUI Components 421
Component class is the root for all GUI components and containers. All Swing GUI compo- Container
nents (except JFrame, JApplet, and JDialog) are subclasses of JComponent, as shown in JComponent
Figure 12.1. Figure 12.11 lists some frequently used methods in Component, Container,
and JComponent for manipulating properties such as font, color, size, tool tip text, and bor-
der.
A tool tip is text displayed on a component when you move the mouse on the component.
It is often used to describe the function of a component.
You can set a border on any object of the JComponent class. Swing has several types of
borders. To create a titled border, use new TitledBorder(String title). To create a line
border, use new LineBorder(Color color, int width), where width specifies the
thickness of the line.
Listing 12.7 is an example to demonstrate Swing common features. The example creates a
panel p1 to hold three buttons (line 8) and a panel p2 to hold two labels (line 25), as shown in
Figure 12.12. The background of the button jbtLeft is set to white (line 12) and the fore-
ground of the button jbtCenter is set to green (line 13). The tool tip of the button jbtRight
is set in line 14. Titled borders are set on panels p1 and p2 (lines 18, 36) and line borders are
set on the labels (lines 32–33).
Titled border Having the mouse cursor
over the Right button
Titled border displays the tool tip text
Line border
FIGURE 12.12 The font, color, border, and tool tip text are set in the message panel. set background
set foreground
LISTING 12.7 TestSwingCommonFeatures.java set tool tip text
1 import java.awt.*; set titled border
2 import javax.swing.*;
3 import javax.swing.border.*; create a font
4 create a border
5 public class TestSwingCommonFeatures extends JFrame {
6 public TestSwingCommonFeatures() {
7 // Create a panel to group three buttons
8 JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 2));
9 JButton jbtLeft = new JButton("Left");
10 JButton jbtCenter = new JButton("Center");
11 JButton jbtRight = new JButton("Right");
12 jbtLeft.setBackground(Color.WHITE);
13 jbtCenter.setForeground(Color.GREEN);
14 jbtRight.setToolTipText("This is the Right button");
15 p1.add(jbtLeft);
16 p1.add(jbtCenter);
17 p1.add(jbtRight);
18 p1.setBorder(new TitledBorder("Three Buttons"));
19
20 // Create a font and a line border
21 Font largeFont = new Font("TimesRoman", Font.BOLD, 20);
22 Border lineBorder = new LineBorder(Color.BLACK, 2);
23
24 // Create a panel to group two labels
422 Chapter 12 GUI Basics
set foreground 25 JPanel p2 = new JPanel(new GridLayout(1, 2, 5, 5));
set font 26 JLabel jlblRed = new JLabel("Red");
set line border 27 JLabel jlblOrange = new JLabel("Orange");
28 jlblRed.setForeground(Color.RED);
set titled border 29 jlblOrange.setForeground(Color.ORANGE);
30 jlblRed.setFont(largeFont);
31 jlblOrange.setFont(largeFont);
32 jlblRed.setBorder(lineBorder);
33 jlblOrange.setBorder(lineBorder);
34 p2.add(jlblRed);
35 p2.add(jlblOrange);
36 p2.setBorder(new TitledBorder("Two Labels"));
37
38 // Add two panels to the frame
39 setLayout(new GridLayout(2, 1, 5, 5));
40 add(p1);
41 add(p2);
42 }
43
44 public static void main(String[] args) {
45 // Create a frame and set its properties
46 JFrame frame = new TestSwingCommonFeatures();
47 frame.setTitle("TestSwingCommonFeatures");
48 frame.setSize(300, 150);
49 frame.setLocationRelativeTo(null); // Center the frame
50 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
51 frame.setVisible(true);
52 }
53 }
property default values Note
The same property may have different default values in different components. For example, the
visible property in JFrame is false by default, but it is true in every instance of
JComponent (e.g., JButton and JLabel) by default. To display a JFrame, you have to
invoke setVisible(true) to set the visible property true, but you don’t have to set this
property for a JButton or a JLabel, because it is already true. To make a JButton or a
JLabel invisible, you may invoke setVisible(false). Please run the program and see the
effect after inserting the following two statements in line 37:
jbtLeft.setVisible(false);
jlblRed.setVisible(false);
image-file format 12.10 Image Icons
create ImageIcon An icon is a fixed-size picture; typically it is small and used to decorate components. Images
file path character are normally stored in image files. Java currently supports three image formats: GIF (Graph-
ics Interchange Format), JPEG (Joint Photographic Experts Group), and PNG (Portable Net-
work Graphics). The image file names for these types end with .gif, .jpg, and .png,
respectively. If you have a bitmap file or image files in other formats, you can use image-pro-
cessing utilities to convert them into GIF, JPEG, or PNG format for use in Java.
To display an image icon, first create an ImageIcon object using new
javax.swing.ImageIcon(filename). For example, the following statement creates an
icon from an image file us.gif in the image directory under the current class path:
ImageIcon icon = new ImageIcon("image/us.gif");
“image/us.gif” is located in “c:\book\image\us.gif.” The back slash (\) is the
Windows file path notation. In Unix, the forward slash (/) should be used. In Java, the forward
12.10 Image Icons 423
slash (/) is used to denote a relative file path under the Java classpath (e.g., image/us.gif, as
in this example).
Tip naming files consistently
File names are not case sensitive in Windows but are case sensitive in Unix. To enable your pro-
grams to run on all platforms, name all the image files consistently, using lowercase.
An image icon can be displayed in a label or a button using new JLabel(image-
Icon) or new JButton(imageIcon). Listing 12.8 demonstrates displaying icons in
labels and buttons. The example creates two labels and two buttons with icons, as shown
in Figure 12.13.
LISTING 12.8 TestImageIcon.java create image icons
1 import javax.swing.*; a label with image
2 import java.awt.*; a button with image
3
4 public class TestImageIcon extends JFrame {
5 private ImageIcon usIcon = new ImageIcon("image/us.gif");
6 private ImageIcon myIcon = new ImageIcon("image/my.jpg");
7 private ImageIcon frIcon = new ImageIcon("image/fr.gif");
8 private ImageIcon ukIcon = new ImageIcon("image/uk.gif");
9
10 public TestImageIcon() {
11 setLayout(new GridLayout(1, 4, 5, 5));
12 add(new JLabel(usIcon));
13 add(new JLabel(myIcon));
14 add(new JButton(frIcon));
15 add(new JButton(ukIcon));
16 }
17
18 /** Main method */
19 public static void main(String[] args) {
20 TestImageIcon frame = new TestImageIcon();
21 frame.setTitle("TestImageIcon");
22 frame.setSize(200, 200);
23 frame.setLocationRelativeTo(null); // Center the frame
24 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
25 frame.setVisible(true);
26 }
27 }
FIGURE 12.13 The image icons are displayed in labels and buttons.
Note
GUI components cannot be shared by containers, because one GUI component can appear in
only one container at a time. Therefore, the relationship between a component and a container is
the composition denoted by a solid diamond, as shown in Figure 12.1.
424 Chapter 12 GUI Basics
sharing borders and icons Note
splash screen
Borders and icons can be shared. Thus you can create a border or icon and use it to set the
border or icon property for any GUI component. For example, the following statements set a
border b for two panels p1 and p2:
p1.setBorder(b);
p2.setBorder(b);
The following statements set an icon in two buttons jbt1 and jbt2:
jbt1.setIcon(icon);
jbt2.setIcon(icon);
Tip
A splash screen is an image that is displayed while the application is starting up. If your program
takes a long time to load, you may display a splash screen to alert the user. For example, the fol-
lowing command:
java –splash:image/us.gif TestImageIcon
displays an image while the program TestImageIcon is being loaded.
KEY TERMS layout manager 411
Swing 406
AWT 406 splash screen 424
heavyweight component 406
lightweight component 406
CHAPTER SUMMARY
1. Every container has a layout manager that is used to position and place components in
the container in the desired locations. Three simple and frequently used layout man-
agers are FlowLayout, GridLayout, and BorderLayout.
2. You can use a JPanel as a subcontainer to group components to achieve a desired layout.
3. Use the add method to place components to a JFrame or a JPanel. By default, the
frame’s layout is BorderLayout, and the JPanel’s layout is FlowLayout.
4. You can set colors for GUI components by using the java.awt.Color class. Colors
are made of red, green, and blue components, each represented by an unsigned byte
value that describes its intensity, ranging from 0 (darkest shade) to 255 (lightest
shade). This is known as the RGB model.
5. To create a Color object, use new Color(r, g, b), in which r, g, and b specify a
color by its red, green, and blue components. Alternatively, you can use one of the 13
standard colors (BLACK, BLUE, CYAN, DARK_GRAY, GRAY, GREEN, LIGHT_GRAY,
MAGENTA, ORANGE, PINK, RED, WHITE, YELLOW) defined as constants in
java.awt.Color.
6. Every Swing GUI component is a subclass of javax.swing.JComponent, and
JComponent is a subclass of java.awt.Component. The properties font,
background, foreground, height, width, and preferredSize in Component
are inherited in these subclasses, as are toolTipText and border in JComponent.
7. You can use borders on any Swing components. You can create an image icon using the
ImageIcon class and display it in a label and a button. Icons and borders can be shared.
Review Questions 425
REVIEW QUESTIONS
Sections 12.3–12.4
12.1 Which class is the root of the Java GUI component classes? Is a container class a
subclass of Component? Which class is the root of the Swing GUI component
classes?
12.2 Explain the difference between AWT GUI components, such as java.awt.Button,
and Swing components, such as javax.swing.JButton.
12.3 How do you create a frame? How do you set the size for a frame? How do you get
the size of a frame? How do you add components to a frame? What would happen
if the statements frame.setSize(400, 300) and frame.setVisible(true)
were swapped in Listing 12.2 MyFrameWithComponents?
12.4 Determine whether the following statements are true or false:
12.5 ■ You can add a button to a frame.
■ You can add a frame to a panel.
■ You can add a panel to a frame.
■ You can add any number of components to a panel or a frame.
■ You can derive a class from JButton, JPanel, or JFrame.
The following program is supposed to display a button in a frame, but nothing is
displayed. What is the problem?
1 public class Test extends javax.swing.JFrame {
2 public Test() {
3 add(new javax.swing.JButton("OK"));
4}
5
6 public static void main(String[] args) {
7 javax.swing.JFrame frame = new javax.swing.JFrame();
8 frame.setSize(100, 200);
9 frame.setVisible(true);
10 }
11 }
12.6 Which of the following statements have syntax errors?
Component c1 = new Component();
JComponent c2 = new JComponent();
Component c3 = new JButton();
JComponent c4 = new JButton();
Container c5 = new JButton();
c5.add(c4);
Object c6 = new JButton();
c5.add(c6);
Sections 12.5
12.7 Why do you need to use layout managers? What is the default layout manager for
a frame? How do you add a component to a frame?
12.8 Describe FlowLayout. How do you create a FlowLayout manager? How do you
add a component to a FlowLayout container? Is there a limit to the number of
components that can be added to a FlowLayout container?
12.9 Describe GridLayout. How do you create a GridLayout manager? How do you
add a component to a GridLayout container? Is there a limit to the number of
components that can be added to a GridLayout container?