- •CONTENTS
- •1.1 Introduction
- •1.2 What Is a Computer?
- •1.3 Programs
- •1.4 Operating Systems
- •1.5 Java, World Wide Web, and Beyond
- •1.6 The Java Language Specification, API, JDK, and IDE
- •1.7 A Simple Java Program
- •1.8 Creating, Compiling, and Executing a Java Program
- •1.9 (GUI) Displaying Text in a Message Dialog Box
- •2.1 Introduction
- •2.2 Writing Simple Programs
- •2.3 Reading Input from the Console
- •2.4 Identifiers
- •2.5 Variables
- •2.7 Named Constants
- •2.8 Numeric Data Types and Operations
- •2.9 Problem: Displaying the Current Time
- •2.10 Shorthand Operators
- •2.11 Numeric Type Conversions
- •2.12 Problem: Computing Loan Payments
- •2.13 Character Data Type and Operations
- •2.14 Problem: Counting Monetary Units
- •2.15 The String Type
- •2.16 Programming Style and Documentation
- •2.17 Programming Errors
- •2.18 (GUI) Getting Input from Input Dialogs
- •3.1 Introduction
- •3.2 boolean Data Type
- •3.3 Problem: A Simple Math Learning Tool
- •3.4 if Statements
- •3.5 Problem: Guessing Birthdays
- •3.6 Two-Way if Statements
- •3.7 Nested if Statements
- •3.8 Common Errors in Selection Statements
- •3.9 Problem: An Improved Math Learning Tool
- •3.10 Problem: Computing Body Mass Index
- •3.11 Problem: Computing Taxes
- •3.12 Logical Operators
- •3.13 Problem: Determining Leap Year
- •3.14 Problem: Lottery
- •3.15 switch Statements
- •3.16 Conditional Expressions
- •3.17 Formatting Console Output
- •3.18 Operator Precedence and Associativity
- •3.19 (GUI) Confirmation Dialogs
- •4.1 Introduction
- •4.2 The while Loop
- •4.3 The do-while Loop
- •4.4 The for Loop
- •4.5 Which Loop to Use?
- •4.6 Nested Loops
- •4.7 Minimizing Numeric Errors
- •4.8 Case Studies
- •4.9 Keywords break and continue
- •4.10 (GUI) Controlling a Loop with a Confirmation Dialog
- •5.1 Introduction
- •5.2 Defining a Method
- •5.3 Calling a Method
- •5.4 void Method Example
- •5.5 Passing Parameters by Values
- •5.6 Modularizing Code
- •5.7 Problem: Converting Decimals to Hexadecimals
- •5.8 Overloading Methods
- •5.9 The Scope of Variables
- •5.10 The Math Class
- •5.11 Case Study: Generating Random Characters
- •5.12 Method Abstraction and Stepwise Refinement
- •6.1 Introduction
- •6.2 Array Basics
- •6.3 Problem: Lotto Numbers
- •6.4 Problem: Deck of Cards
- •6.5 Copying Arrays
- •6.6 Passing Arrays to Methods
- •6.7 Returning an Array from a Method
- •6.8 Variable-Length Argument Lists
- •6.9 Searching Arrays
- •6.10 Sorting Arrays
- •6.11 The Arrays Class
- •7.1 Introduction
- •7.2 Two-Dimensional Array Basics
- •7.3 Processing Two-Dimensional Arrays
- •7.4 Passing Two-Dimensional Arrays to Methods
- •7.5 Problem: Grading a Multiple-Choice Test
- •7.6 Problem: Finding a Closest Pair
- •7.7 Problem: Sudoku
- •7.8 Multidimensional Arrays
- •8.1 Introduction
- •8.2 Defining Classes for Objects
- •8.3 Example: Defining Classes and Creating Objects
- •8.4 Constructing Objects Using Constructors
- •8.5 Accessing Objects via Reference Variables
- •8.6 Using Classes from the Java Library
- •8.7 Static Variables, Constants, and Methods
- •8.8 Visibility Modifiers
- •8.9 Data Field Encapsulation
- •8.10 Passing Objects to Methods
- •8.11 Array of Objects
- •9.1 Introduction
- •9.2 The String Class
- •9.3 The Character Class
- •9.4 The StringBuilder/StringBuffer Class
- •9.5 Command-Line Arguments
- •9.6 The File Class
- •9.7 File Input and Output
- •9.8 (GUI) File Dialogs
- •10.1 Introduction
- •10.2 Immutable Objects and Classes
- •10.3 The Scope of Variables
- •10.4 The this Reference
- •10.5 Class Abstraction and Encapsulation
- •10.6 Object-Oriented Thinking
- •10.7 Object Composition
- •10.8 Designing the Course Class
- •10.9 Designing a Class for Stacks
- •10.10 Designing the GuessDate Class
- •10.11 Class Design Guidelines
- •11.1 Introduction
- •11.2 Superclasses and Subclasses
- •11.3 Using the super Keyword
- •11.4 Overriding Methods
- •11.5 Overriding vs. Overloading
- •11.6 The Object Class and Its toString() Method
- •11.7 Polymorphism
- •11.8 Dynamic Binding
- •11.9 Casting Objects and the instanceof Operator
- •11.11 The ArrayList Class
- •11.12 A Custom Stack Class
- •11.13 The protected Data and Methods
- •11.14 Preventing Extending and Overriding
- •12.1 Introduction
- •12.2 Swing vs. AWT
- •12.3 The Java GUI API
- •12.4 Frames
- •12.5 Layout Managers
- •12.6 Using Panels as Subcontainers
- •12.7 The Color Class
- •12.8 The Font Class
- •12.9 Common Features of Swing GUI Components
- •12.10 Image Icons
- •13.1 Introduction
- •13.2 Exception-Handling Overview
- •13.3 Exception-Handling Advantages
- •13.4 Exception Types
- •13.5 More on Exception Handling
- •13.6 The finally Clause
- •13.7 When to Use Exceptions
- •13.8 Rethrowing Exceptions
- •13.9 Chained Exceptions
- •13.10 Creating Custom Exception Classes
- •14.1 Introduction
- •14.2 Abstract Classes
- •14.3 Example: Calendar and GregorianCalendar
- •14.4 Interfaces
- •14.5 Example: The Comparable Interface
- •14.6 Example: The ActionListener Interface
- •14.7 Example: The Cloneable Interface
- •14.8 Interfaces vs. Abstract Classes
- •14.9 Processing Primitive Data Type Values as Objects
- •14.10 Sorting an Array of Objects
- •14.11 Automatic Conversion between Primitive Types and Wrapper Class Types
- •14.12 The BigInteger and BigDecimal Classes
- •14.13 Case Study: The Rational Class
- •15.1 Introduction
- •15.2 Graphical Coordinate Systems
- •15.3 The Graphics Class
- •15.4 Drawing Strings, Lines, Rectangles, and Ovals
- •15.5 Case Study: The FigurePanel Class
- •15.6 Drawing Arcs
- •15.7 Drawing Polygons and Polylines
- •15.8 Centering a String Using the FontMetrics Class
- •15.9 Case Study: The MessagePanel Class
- •15.10 Case Study: The StillClock Class
- •15.11 Displaying Images
- •15.12 Case Study: The ImageViewer Class
- •16.1 Introduction
- •16.2 Event and Event Source
- •16.3 Listeners, Registrations, and Handling Events
- •16.4 Inner Classes
- •16.5 Anonymous Class Listeners
- •16.6 Alternative Ways of Defining Listener Classes
- •16.7 Problem: Loan Calculator
- •16.8 Window Events
- •16.9 Listener Interface Adapters
- •16.10 Mouse Events
- •16.11 Key Events
- •16.12 Animation Using the Timer Class
- •17.1 Introduction
- •17.2 Buttons
- •17.3 Check Boxes
- •17.4 Radio Buttons
- •17.5 Labels
- •17.6 Text Fields
- •17.7 Text Areas
- •17.8 Combo Boxes
- •17.9 Lists
- •17.10 Scroll Bars
- •17.11 Sliders
- •17.12 Creating Multiple Windows
- •18.1 Introduction
- •18.2 Developing Applets
- •18.3 The HTML File and the <applet> Tag
- •18.4 Applet Security Restrictions
- •18.5 Enabling Applets to Run as Applications
- •18.6 Applet Life-Cycle Methods
- •18.7 Passing Strings to Applets
- •18.8 Case Study: Bouncing Ball
- •18.9 Case Study: TicTacToe
- •18.10 Locating Resources Using the URL Class
- •18.11 Playing Audio in Any Java Program
- •18.12 Case Study: Multimedia Animations
- •19.1 Introduction
- •19.2 How is I/O Handled in Java?
- •19.3 Text I/O vs. Binary I/O
- •19.4 Binary I/O Classes
- •19.5 Problem: Copying Files
- •19.6 Object I/O
- •19.7 Random-Access Files
- •20.1 Introduction
- •20.2 Problem: Computing Factorials
- •20.3 Problem: Computing Fibonacci Numbers
- •20.4 Problem Solving Using Recursion
- •20.5 Recursive Helper Methods
- •20.6 Problem: Finding the Directory Size
- •20.7 Problem: Towers of Hanoi
- •20.8 Problem: Fractals
- •20.9 Problem: Eight Queens
- •20.10 Recursion vs. Iteration
- •20.11 Tail Recursion
- •APPENDIXES
- •INDEX
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 constructors? 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 constructor; 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 constructors of a superclass are not inherited in the subclass. They can only be invoked from the constructors of the subclasses, using the keyword super.
11.3.2Constructor 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 constructor. For example,
public ClassName() { |
|
|
|
public ClassName() { |
|||
// some statements |
|
Equivalent |
|
super(); |
|
||
} |
|
} |
// some statements |
||||
|
|
|
|||||
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public ClassName(double d) { |
|
|
|
public ClassName(double d) { |
|||
// some statements |
|
Equivalent |
|
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 along the inheritance chain. When constructing an object of a subclass, the subclass constructor 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 |
{ |
2 |
public static void |
main(String[] args) { |
3new Faculty();
4 |
} |
5 |
|
6public Faculty() {
7System.out.println("(4) Performs Faculty's tasks");
8 |
} |
|
|
9 |
} |
|
|
10 |
|
|
|
11 |
class |
Employee extends Person |
{ |
12public Employee() {
13this("(2) Invoke Employee's overloaded constructor");
14System.out.println("(3) Performs Employee's tasks ");
15}
16
17public Employee(String s) {
18System.out.println(s);
19}
20}
21
22 class Person {
23public Person() {
24System.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
constructor chaining
invoke overloaded constructor
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 constructor (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(String s) |
|
Person() |
|
Employee() |
|
|
|||
{ |
|
{ this("(2) ..."); |
|
{ |
|
{ |
Performs Faculty's |
|
Performs Employee's |
|
Performs Employee's |
|
Performs Person's |
tasks; |
|
tasks; |
|
tasks; |
|
tasks; |
} |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
382 Chapter 11 |
Inheritance and Polymorphism |
|
Caution |
no-arg constructor |
If a class is designed to be extended, it is better to provide a no-arg constructor to avoid pro- |
|
gramming errors. Consider the following code: |
1 public class Apple extends Fruit {
2 }
3
4 class Fruit {
5public Fruit(String name) {
6System.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 automatically 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 |
no-arg constructor |
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.3Calling 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 |
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() { |
||
toString in superclass |
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 class. Both methods can be used in the Circle class. To invoke the toString method defined in 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 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.
■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. The hidden static methods can be invoked using the syntax SuperClassName.staticMethodName.
no super.super. methodName()
override accessible instance method
cannot override static method
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 static void main(String[] args) { A a = new A();
a.p(10); a.p(10.0);
}
}
class B {
public void p(double i) { System.out.println(i * 2);
}
}
class A extends B {
// This method overrides the method in B
public void p(double i ) { System.out.println(i);
}
}
(a)
public class Test {
public static void main(String[] args) { A a = new A();
a.p(10); a.p(10.0);
}
}
class B {
public void p(double i) { System.out.println(i * 2);
}
}
class A extends B {
// This method overloads the method in B
public void p(int i ) { System.out.println(i);
}
}
(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.