- •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
432Chapter 13 Exception Handling
13.1Introduction
Runtime errors occur while a program is running if the environment detects an operation that is impossible to carry out. For example, if you access an array using an index out of bounds, your program will get a runtime error with an ArrayIndexOutOfBoundsException. To read data from a file, you need to create a Scanner object using new Scanner(new File(filename)) (see Listing 9.6). If the file does not exist, your program will get a runtime error with a FileNotFoundException.
In Java, runtime errors are caused by exceptions. An exception is an object that represents an error or a condition that prevents execution from proceeding normally. If the exception is not handled, the program will terminate abnormally. How can you handle the exception so that the program can continue to run or else terminate gracefully? This is the subject we introduce in this chapter.
Video Note
Exception-handling advantages
reads two integers
integer division
13.2 Exception-Handling Overview
To demonstrate exception handling, including how an exception object is created and thrown, we begin with an example (Listing 13.1) that reads in two integers and displays their quotient.
LISTING 13.1 Quotient.java
1 import java.util.Scanner;
2
3 public class Quotient {
4 public static void main(String[] args) {
5 Scanner input = new Scanner(System.in);
6
7 // Prompt the user to enter two integers
8 System.out.print("Enter two integers: ");
9 int number1 = input.nextInt();
10 int number2 = input.nextInt();
11
12System.out.println(number1 + " / " + number2 + " is " +
13(number1 / number2));
14}
15}
Enter two integers: 5 2 5 / 2 is 2
Enter two integers: 3 0
Exception in thread "main" java.lang.ArithmeticException: / by zero at Quotient.main(Quotient.java:11)
If you entered 0 for the second number, a runtime error would occur, because you cannot divide an integer by 0. (Recall that a floating-point number divided by 0 does not raise an exception.) A simple way to fix the error is to add an if statement to test the second number, as shown in Listing 13.2.
LISTING 13.2 QuotientWithIf.java
1 import java.util.Scanner;
2
3 public class QuotientWithIf {
13.2 Exception-Handling Overview 433
4 public static void main(String[] args) {
5 Scanner input = new Scanner(System.in);
6
7 // Prompt the user to enter two integers
8System.out.print("Enter two integers: ");
9 |
int number1 = input.nextInt(); |
reads two integers |
10 |
int number2 = input.nextInt(); |
|
11 |
|
|
12 |
if (number2 != 0) |
test number2 |
13System.out.println(number1 + " / " + number2
14+ " is " + (number1 / number2));
15else
16System.out.println("Divisor cannot be zero ");
17}
18}
Enter two integers: 5 0
Divisor cannot be zero
In order to demonstrate the concept of exception handling, including how to create, throw, catch, and handle an exception, we rewrite Listing 13.2 as shown in Listing 13.3.
LISTING 13.3 QuotientWithException.java
1 import java.util.Scanner;
2
3 public class QuotientWithException {
4 public static void main(String[] args) {
5 Scanner input = new Scanner(System.in);
6
7 // Prompt the user to enter two integers
8System.out.print("Enter two integers: ");
9 |
int number1 = input.nextInt(); |
reads two integers |
||
10 |
int number2 = input.nextInt(); |
|
||
11 |
|
|
|
|
12 |
|
try { |
|
try block |
13if (number2 == 0)
14throw new ArithmeticException("Divisor cannot be zero");
15
16System.out.println(number1 + " / " + number2 + " is " +
17(number1 / number2));
18}
19 |
catch (ArithmeticException ex) { |
catch block |
20System.out.println("Exception: an integer " +
21"cannot be divided by zero ");
22}
23
24System.out.println("Execution continues ...");
25}
26}
Enter two integers: 5 3 5 / 3 is 1
Execution continues ...
434 Chapter 13 Exception Handling
Enter two integers: 5 0
Exception: an integer cannot be divided by zero
Execution continues ...
|
The program contains a try block and a catch block. The try block (lines 12–18) contains |
|
the code that is executed in normal circumstances. The catch block (lines 19–22) contains |
|
the code that is executed when number2 is 0. In this event the program throws an exception |
|
by executing |
throw statement |
throw new ArithmeticException("Divisor cannot be zero"); |
|
The value thrown, in this case new ArithmeticException("Divisor cannot be |
exception |
zero"), is called an exception. The execution of a throw statement is called throwing an |
throwing exception |
exception. The exception is an object created from an exception class. In this case, the excep- |
|
tion class is java.lang.ArithmeticException. |
|
When an exception is thrown, the normal execution flow is interrupted. As the name sug- |
|
gests, to “throw an exception” is to pass the exception from one place to another. The excep- |
handle exception |
tion is caught by the catch block. The code in the catch block is executed to handle the |
|
exception. Afterward, the statement (line 24) after the catch block is executed. |
|
The throw statement is analogous to a method call, but instead of calling a method, it calls |
|
a catch block. In this sense, a catch block is like a method definition with a parameter that |
|
matches the type of the value being thrown. Unlike a method, after the catch block is exe- |
|
cuted, however, the program control does not return to the throw statement; instead, it exe- |
|
cutes the next statement after the catch block. |
|
The identifier ex in the catch–block header |
|
catch (ArithmeticException ex) |
|
acts very much like a parameter in a method. So this parameter is referred to as a |
catch–block parameter |
catch–block parameter. The type (e.g., ArithmeticException) preceding ex specifies |
|
what kind of exception the catch block can catch. Once the exception is caught, you can |
|
access the thrown value from this parameter in the body of a catch block. |
|
In summary, a template for a try-throw-catch block may look like this: |
|
try { |
Code to try;
Throw an exception with a throw statement or from method if necessary;
More code to try;
}
catch (type ex) {
Code to process the exception;
}
An exception may be thrown directly by using a throw statement in a try block, or by invoking a method that may throw an exception.
13.3 Exception-Handling Advantages
You have seen from Listing 13.3 how an exception is created, thrown, caught, and handled. You may wonder what the benefits are. To see these benefits, we rewrite Listing 13.3 to compute a quotient using a method, as shown in Listing 13.4.
13.3 Exception-Handling Advantages 435
LISTING 13.4 QuotientWithMethod.java
1 |
import java.util.Scanner; |
|
|
2 |
|
|
|
3 |
public class QuotientWithMethod { |
|
|
4 |
|
public static int quotient(int number1, int number2) { |
quotient method |
5if (number2 == 0)
6 |
|
throw new ArithmeticException("Divisor cannot be zero"); |
throw exception |
7 |
|
|
|
8 |
return number1 / number2; |
|
|
9 |
} |
|
|
10 |
|
|
|
11public static void main(String[] args) {
12Scanner input = new Scanner(System.in);
14// Prompt the user to enter two integers
15System.out.print("Enter two integers: ");
16 |
|
int |
number1 = input.nextInt(); |
reads two integers |
||||||
17 |
|
int |
number2 = input.nextInt(); |
|
||||||
18 |
|
|
|
|
|
|
|
|
|
|
19 |
|
try |
{ |
|
|
|
try block |
|||
20 |
|
|
|
|
int result = quotient(number1, number2); |
|
invoke method |
|||
If an |
|
|
|
|
||||||
21 |
Arithmetic System.out.println(number1 + " / " + number2 + " is " |
|
||||||||
22 |
Exception |
+ result); |
|
|||||||
23 |
occurs |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
24 |
|
catch (ArithmeticException ex) { |
|
|
catch block |
|||||
25 |
|
|
|
|
System.out.println("Exception: an integer " + |
|
||||
|
|
|
|
|
26"cannot be divided by zero ");
27}
28
29System.out.println("Execution continues ...");
30}
31}
Enter two integers: 5 3 5 / 3 is 1
Execution continues ...
Enter two integers: 5 0
Exception: an integer cannot be divided by zero
Execution continues ...
Method quotient (lines 4–9) returns the quotient of two integers. If number2 is 0, it cannot return a value. So, an exception is thrown in line 6.
The main method invokes quotient (line 20). If the quotient method executes normally, it returns a value to the caller. If the quotient method encounters an exception, it throws the exception back to its caller. The caller’s catch block handles the exception.
Now you see the advantages of using exception handling. It enables a method to throw an advantage exception to its caller. The caller can handle this exception. Without this capability, the called
method itself must handle the exception or terminate the program. Often the called method does not know what to do in case of error. This is typically the case for the library methods. The library method can detect the error, but only the caller knows what needs to be done when
436 Chapter 13 Exception Handling
an error occurs. The essential benefit of exception handling is to separate the detection of an error (done in a called method) from the handling of an error (done in the calling method).
Many library methods throw exceptions. Listing 13.5 gives an example that handles
FileNotFoundException for invoking the Scanner(File file) constructor.
LISTING 13.5 FileNotFoundExceptionDemo.java
|
1 |
import java.util.Scanner; |
|||||||
|
2 |
import java.io.*; |
|||||||
|
3 |
|
|
|
|
|
|
|
|
|
4 |
public class FileNotFoundExceptionDemo { |
|||||||
|
5 |
public static void main(String[] args) { |
|||||||
|
6 |
|
Scanner inputFromConsole = new Scanner(System.in); |
||||||
|
7 |
|
// Prompt the user to enter a file name |
||||||
|
8 |
|
System.out.print("Enter a file name: "); |
||||||
|
9 |
|
String filename = inputFromConsole.nextLine(); |
||||||
|
10 |
|
|
|
|
|
|
|
|
try block |
11 |
|
try { |
|
|||||
create a Scanner |
12 |
|
|
|
|
Scanner inputFromFile = new Scanner(new File(filename)); |
|
||
If a |
|
|
|
|
|||||
|
13 |
FileNot- System.out.println("File " + filename + " exists "); |
|||||||
|
14 |
Found |
|
|
|
// Processing file ... |
|||
|
15 |
Exception |
|
|
|
|
|||
|
occurs |
} |
|
|
|
|
|
||
catch block |
16 |
|
catch (FileNotFoundException ex) { |
|
|
||||
|
17 |
|
|
|
|
System.out.println("Exception: " + filename + " not found"); |
|||
|
|
|
|
|
|||||
|
18 |
|
} |
|
|
|
|
|
|
|
19 |
} |
|
|
|
|
|
|
|
|
20 |
} |
|
|
|
|
|
|
|
Enter a file name: c:\book\Welcome.java
File c:\book\Welcome.java exists
Enter a file name: c:\book\Test10.java
Exception: c:\book\Test10.java not found
The program creates a Scanner for a file (line 12). If the file does not exist, the constructor throws a FileNotFoundException, which is caught in the catch block.
Listing 13.6 gives an example that handles an InputMismatchException exception.
LISTING 13.6 InputMismatchExceptionDemo.java
|
1 |
import java.util.*; |
|||||
|
2 |
|
|
|
|
|
|
|
3 |
public class InputMismatchExceptionDemo { |
|||||
|
4 |
public static void main(String[] args) { |
|||||
|
5 |
Scanner input = new Scanner(System.in); |
|||||
|
6 |
boolean continueInput = true; |
|||||
|
7 |
|
|
|
|
|
|
|
8 |
do { |
|
|
|
||
|
9 |
|
try |
{ |
|||
|
10 |
|
|
|
System.out.print("Enter an integer: "); |
||
try block |
11 |
|
|
int number = input.nextInt(); |
|
||
If an InputMi |
|
||||||
create a Scanner |
|
|
|
||||
12 |
smatchExcep- |
|
|
|
|||
|
13 |
tion occurs |
// Display the result |
||||
|
14 |
|
|
|
System.out.println( |