7.1. Exceptions in Java

[8.3] Describe the advantages of Exception handling

In this section, you’ll learn what exceptions are in Java, why you need to handle exceptions separately from the main code, and all about their advantages and disadvantages.

7.1.1. A taste of exceptions

In figure 7.1, do you think the code in bold in the classes ArrayAccess, OpenFile, and MethodAccess has anything in common?

Figure 7.1. Getting a taste of exceptions in Java

I’m sure, given this chapter’s title, that this question was easy to answer. Each of these three statements is associated with throwing an exception or an error. Let’s look at them individually:

  • Class ArrayAccess—Because the length of the array students is 3, trying to access the element at array position 5 is an exceptional condition, as shown in figure 7.2.
    Figure 7.2. An example of ArrayIndexOutOfBoundsException

  • Class OpenFile—The constructor of the class FileInputStream throws a checked exception, FileNotFoundException (as shown in figure 7.3). If you try to compile this code without enclosing it within a try block and catching it, or marking it to be thrown by the method main (by using the throws statement), or catching this exception, your code will fail to compile. (I’ll discuss checked exceptions in detail in section 7.2.3.)
    Figure 7.3. An example of FileNotFoundException

  • Class MethodAccess—As you can see in figure 7.4, the method myMethod calls itself recursively, without specifying an exit condition. These recursive calls result in a StackOverflowError at runtime.
    Figure 7.4. An example of StackOverflowError

These examples of exceptions are typical of what you’ll find on the OCA Java SE 8 Programmer I exam. Let’s move on and explore exceptions and their handling in Java so that you can spot code that throws exceptions and handle them accordingly.

File I/O in Java

File I/O isn’t covered on this exam, but you may notice it mentioned in questions related to exception handling. I’ll cover it quickly here just to the extent required for this exam.

File I/O involves multiple classes that enable you to read data from and write it to a source. This data source can be persistent storage, memory, or even network connections. Data can be read and written as streams of binary or character data. Some file I/O classes only read data from a source, some write data to a source, and some do both.

In this chapter, you’ll work with three classes from the file I/O API: java.io.File, java.io.FileInputStream, and java.io.FileOutputStream. File is an abstract representation of file and directory pathnames. You can open a File and then read from and write to it. A FileInputStream obtains input bytes using an object of the class File. It defines the methods read to read bytes and close to close this stream. A FileOutputStream is an output stream for writing data to a File. It defines the methods write to write bytes and close to close this stream.

Creating an object of the class FileInputStream or FileOutputStream can throw the checked exception java.io.FileNotFoundException. The methods read, write, and close defined in classes FileInputStream and FileOutputStream can throw the checked exception java.io.IOException. Note that FileNotFound-Exception subclasses IOException.

7.1.2. Why handle exceptions separately?

Imagine you want to post some comments on a blogging website. To make a comment, you must complete the following steps:

  1. Access the blogging website.
  2. Log into your account.
  3. Select the blog you want to comment on.
  4. Post your comments.

The preceding list might seem like an ideal set of steps. In actual conditions, you may have to verify whether you’ve completed a previous step before you can progress with the next step. Figure 7.5 modifies the previous steps.

Figure 7.5. Expected code flow lost in combating exception conditions, without separate exception handlers

The modified logic (figure 7.5) requires the code to check conditions before a user can continue with the next step. This checking of conditions at multiple places introduces new steps for users and also new paths of execution of the original steps. The difficult part of these modified paths is that they may leave users confused about the steps involved in the tasks they’re trying to accomplish. Figure 7.6 shows how exception handling can help.

Figure 7.6. Defining exception-handling code separate from the main code logic

The code in figure 7.6 defines the original steps required to post comments to a blog, along with some exception-handling code. Because the exception handlers are defined separately, any confusion with what steps you need to accomplish to post comments on the website has been clarified. In addition, this code doesn’t compromise on checking the completion of a step before moving on to the next step, courtesy of appropriate exception handlers.

7.1.3. Does exception handling offer any other benefits?

Apart from separating concerns between defining the regular program logic and the exception-handling code, exceptions also can help pinpoint the offending code (code that throws an exception), together with the method in which it is defined, by providing a stack trace of the exception or error.

Note

A stack trace is so called because it gives you a way to trace back the stack—the sequence of method calls that generated the error (covered in detail in section 7.2).

Here’s an example:

public class Trace {                                   // line 1
    public static void main(String args[]) {           // line 2
        method1();                                     // line 3
    }                                                  // line 4
    public static void method1() {                     // line 5
        method2();                                     // line 6
    }                                                  // line 7

    public static void method2() {                     // line 8
        String[] students = {"Shreya", "Joseph"};      // line 9
        System.out.println(students[5]);               // line 10
    }                                                  // line 11
}                                                      // line 12

method2() tries to access the array element of students at index 5, which is an invalid index for the array students, so the code throws the exception ArrayIndexOutOfBoundsException at runtime. Figure 7.7 shows the stack trace when this exception is thrown. It includes the runtime exception message and the list of methods that were involved in calling the code that threw the exception, starting from the entry point of this application, the main method. You can match the line numbers specified in the stack trace in figure 7.7 to the line numbers in the code.

Figure 7.7. Tracing the line of code that threw an exception at runtime

Note

The stack trace gives you a trace of the methods that were called when the JVM encountered an unhandled exception. Stack traces are read from the bottom up. In figure 7.7, the trace starts with the main method (the last line of the stack trace) and continues up to the method containing the code that threw the exception. Depending on the complexity of your code, a stack trace can range from a few lines to hundreds of lines of code. A stack trace works with handled and unhandled exceptions.

Let’s move on and look at more details of exception propagation and at the creation of try-catch-finally blocks to take care of exceptions in code.

Before diving into the details of exception handling, let’s look at the multiple flavors of exceptions.

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

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