Exceptions

Although you are just learning about them now, you have probably become well-acquainted with exceptions during the last 17 previous hours. These errors turn up when you write a Java program that compiles successfully but encounters a problem as it runs.

For example, a common programming mistake is to refer to an element of an array that doesn’t exist, as in the following statements:

String[] greek = { "Alpha", "Beta", "Gamma" };
System.out.println(greek[3]);

The String array greek has three elements. Because the first element of an array is numbered 0 rather than 1, the first element is greek[0], the second greek[1], and the third greek[2]. So the statement attempting to display greek[3] is erroneous. The preceding statements compile successfully, but when you run the program, the Java interpreter halts with a message such as the following:

Output


Exception in thread "main" java.lang.ArrayIndexOutBoundsException: 3
    at SampleProgram.main(SampleProgram.java:4)


This message indicates that the application has generated an exception, which the interpreter noted by displaying an error message and stopping the program.

The error message refers to a class called ArrayIndexOutOfBoundsException in the java.lang package. This class is an exception, an object that represents an exceptional circumstance that has taken place in a Java program.

When a Java class encounters an exception, it alerts users of the class to the error. In this example, the user of the class is the Java interpreter.


Note

Two terms are used to describe this process: throw and catch. Objects throw exceptions to alert others that they have occurred. These exceptions are caught by other objects or the Java interpreter.


All exceptions are subclasses of Exception in the java.lang package. The ArrayIndexOutOfBoundsException does what you would expect—it reports that an array element has been accessed outside the array’s boundaries.

There are hundreds of exceptions in Java. Many such as the array exception indicate a problem that can be fixed with a programming change. These are comparable to compiler errors—after you correct the situation, you don’t have to concern yourself with the exception any longer.

Other exceptions must be dealt with every time a program runs by using five new keywords: try, catch, finally, throw, and throws.

Catching Exceptions in a try-catch Block

Up to this point, you have dealt with exceptions by fixing the problem that caused them. There are times you can’t deal with an exception in that manner and must handle the issue within a Java class.

As an introduction to why this is useful, enter the short Java application in Listing 18.1 in a new empty Java file called Calculator and save the file.

Listing 18.1. The Full Text of Calculator.java


 1: public class Calculator {
 2:     public static void main(String[] arguments) {
 3:         float sum = 0;
 4:         for (int i = 0; i < arguments.length; i++) {
 5:             sum = sum + Float.parseFloat(arguments[i]);
 6:         }
 7:         System.out.println("Those numbers add up to " + sum);
 8:     }
 9: }


The Calculator application takes one or more numbers as command-line arguments, adds them up, and displays the total.

Because all command-line arguments are represented by strings in a Java application, the program must convert them into floating-point numbers before adding them together. The Float.parseFloat() class method in Line 5 takes care of this, adding the converted number to a variable named sum.

Before running the application with the following command-line arguments, which can be set in NetBeans with the Run, Set Project Configuration, Customize command: 8 6 7 5 3 0 9. Choose Run, Run Main Project to run the application and see the output in Figure 18.1.

Figure 18.1. The output of the Calculator application.

Image

Run the program several times with different numbers as arguments. It should handle them successfully, which might make you wonder what this has to do with exceptions.

To see the relevance, change the Calculator application’s command-line arguments to 1 3 5x.

The third argument contains a typo—there shouldn’t be an x after the number 5. The Calculator application has no way to know this is a mistake, so it tries to add 5x to the other numbers, causing the following exception to be displayed:

Output


Exception in thread "main" java.lang.NumberFormatException: For input
string: "5x" at sun.misc.FloatingDecimal.readJavaFormatString
(FloatingDecimal.java:1224)
    at java.lang.Float.parseFloat(Float.java:422)
    at Calculator.main(Calculator.java:5)


This message can be informative to a programmer, but it’s not something you’d want a user to see. Java programs can take care of their own exceptions by using a try-catch block statement, which takes the following form:

try {
    // statements that might cause the exception
} catch (Exception e) {
   // what to do when the exception occurs
}

A try-catch block must be used on any exception that you want a method of a class to handle. The Exception object that appears in the catch statement should be one of three things:

• The class of the exception that might occur

• More than one class of exception, separated by | characters

• A superclass of several different exceptions that might occur

The try section of the try-catch block contains the statement (or statements) that might throw an exception. In the Calculator application, the call to the Float.parseFloat(String) method in Line 5 of Listing 18.1 throws a NumberFormatException whenever it is used with a string argument that can’t be converted to a floating-point value.

To improve the Calculator application so that it never stops running with this kind of error, you can use a try-catch block.

Create a new empty Java file called NewCalculator and enter the text of Listing 18.2.

Listing 18.2. The Full Text of NewCalculator.java


 1: public class NewCalculator {
 2:     public static void main(String[] arguments) {
 3:         float sum = 0;
 4:         for (int i = 0; i < arguments.length; i++) {
 5:             try {
 6:                 sum = sum + Float.parseFloat(arguments[i]);
 7:             } catch (NumberFormatException e) {
 8:                 System.out.println(arguments[i] + " is not a number.");
 9:             }
10:         }
11:        System.out.println("Those numbers add up to " + sum);
12:     }
13: }


After you save the application, run it with the command-line argument 1 3 5x and you see the output shown in Figure 18.2.

Figure 18.2. The output of the NewCalculator application.

Image

The try-catch block in Lines 5–9 deals with NumberFormatException errors thrown by Float.parseFloat(). These exceptions are caught within the NewCalculator class, which displays an error message for any argument that is not a number. Because the exception is handled within the class, the Java interpreter does not display an error. You can often deal with problems related to user input and other unexpected data by using try-catch blocks.

Catching Several Different Exceptions

A try-catch block can be used to handle several different kinds of exceptions, even if they are thrown by different statements.

One way to handle multiple classes of exceptions is to devote a catch block to each one, as in this code:

String textValue = "35";
int value;
try {
    value = Integer.parseInt(textValue);
catch (NumberFormatException exc) {
    // code to handle exception
} catch (Arithmetic Exception exc) {
    // code to handle exception
}

As of Java 7, you also can handle multiple exceptions in the same catch block by separating them with pipe (|) characters and ending the list with a name for the exception variable. Here’s an example:

try {
    value = Integer.parseInt(textValue);
catch (NumberFormatException | Arithmetic Exception exc) {
    // code to handle exceptions
}

If a NumberFormatException or ArithmeticException is caught, it will be assigned to the exc variable.

Listing 18.3 contains an application called NumberDivider that takes two integer arguments from the command-line and uses them in a division expression.

This application must be able to deal with two potential problems in user input:

• Nonnumeric arguments

• Division by zero

Create a new empty Java file for NumberDivider and enter the text of Listing 18.3 into the source editor.

Listing 18.3. The Full Text of NumberDivider.java


 1: public class NumberDivider {
 2:     public static void main(String[] arguments) {
 3:         if (arguments.length == 2) {
 4:             int result = 0;
 5:             try {
 6:                 result = Integer.parseInt(arguments[0]) /
 7:                     Integer.parseInt(arguments[1]);
 8:                 System.out.println(arguments[0] + " divided by " +
 9:                     arguments[1] + " equals " + result);
10:             } catch (NumberFormatException e) {
11:                 System.out.println("Both arguments must be numbers.");
12:             } catch (ArithmeticException e) {
13:                 System.out.println("You cannot divide by zero.");
14:             }
15:         }
16:     }
17: }


Using command-line arguments to specify two arguments, you can run it with integers, floating-point numbers, and nonnumeric arguments.

The if statement in Line 3 checks to make sure that two arguments are sent to the application. If not, the program exits without displaying anything.

The NumberDivider application performs integer division, so the result is an integer. In integer division, 5 divided by 2 equals 2, not 2.5.

If you use a floating-point or nonnumeric argument, a NumberFormatException is thrown by Lines 6–7 and caught by Lines 10–11.

If you use an integer as the first argument and a zero as the second argument, a ArithmeticExpression is thrown in Lines 6–7 and caught by Lines 12–13.

Handling Something After an Exception

When you are dealing with multiple exceptions by using try and catch, there are times when you want the program to do something at the end of the block whether an exception occurred or not.

You can handle this by using a try-catch-finally block, which takes the following form:

try {
    // statements that might cause the exception
} catch (Exception e) {
   // what to do when the exception occurs
} finally {
    // statements to execute no matter what
}

The statement or statements within the finally section of the block is executed after everything else in the block, even if an exception occurs.

One place this is useful is in a program that reads data from a file on disk, which you do in Hour 20, “Reading and Writing Files.” There are several ways an exception can occur when you are accessing data—the file might not exist, a disk error could occur, and so on. If the statements to read the disk are in a try section and errors are handled in a catch section, you can close the file in the finally section. This makes sure that the file is closed whether or not an exception is thrown as it is read.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.166.45