Chapter 10 Exceptions Notes Flashcards

Exceptions

1
Q

Understanding Exceptions

A
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

THE ROLE OF EXCEPTIONS

A
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

RETURN CODES VS. EXCEPTIONS

A
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

UNDERSTANDING EXCEPTION TYPES

A

Java has a Throwable superclass for all objects that represent these events.

FIGURE 10.1 Categories of exception
~~~
java.lang.Object
^
|
java.lang.Throwable
^ ^
| |
java.lang.Exception java.lang.Error
^
|
java.lang.RuntimeException
~~~

  • For the exam, the only thing you need to know about Throwable is that it’s the parent class of all exceptions, including the Error class.
  • While you can handle Throwable and Error exceptions, it is not recommended you do so in your application code.
  • In this chapter, when we refer to exceptions, we generally mean any class that inherits Throwable, although we are almost always working with the Exception class or subclasses of it.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Checked Exceptions

A
  • A checked exception is an exception that must be declared or handled by the application code where it is thrown.
  • In Java, checked exceptions all inherit Exception but not RuntimeException.
  • Checked exceptions tend to be more anticipated—for example, trying to read a file that doesn’t exist.
  • Checked exceptions also include any class that inherits Throwable, but not Error or RuntimeException.
  • For example, a class that directly extends Throwable would be a checked exception.
  • For the exam, though, you just need to know about checked exceptions that extend Exception.
  • Java has a rule called the handle or declare rule.
  • The handle or declare rule means that all checked exceptions that could be thrown within a method are either wrapped in compatible try and catch blocks or declared in the method signature.

Let’s take a look at an example. The following fall() method declares that it might throw an IOException, which is a checked exception:

void fall(int distance) throws IOException {
    if(distance > 10) {
        throw new IOException();
    }
}
  • Notice that you’re using two different keywords here.
  • The throw keyword tells Java that you want to throw an Exception,
  • while the throws keyword simply declares that the method might throw an Exception. It also might not.
  • You will see the throws keyword again later in the chapter.

Now that you know how to declare an exception, how do you instead handle it? The following alternate version of the fall() method handles the exception:

void fall(int distance) {
    try {
        if(distance > 10) {
            throw new IOException();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • Notice that the catch statement uses Exception, not IOException.
  • Since IOException is a subclass of Exception, the catch block is allowed to catch it.
  • We’ll cover try and catch blocks in more detail later in this chapter.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

handle or declare

A
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

> [!NOTE]
While only checked exceptions must be handled or declared in Java,
unchecked exceptions (which we will present in the next section) may also be handled or declared.
The distinction is that checked exceptions must be handled or declared, while unchecked exceptions can be optionally handled or declared.

A
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Unchecked Exceptions

A
  • An unchecked exception is any exception that does not need to be declared or handled by the application code where it is thrown.
  • Unchecked exceptions are often referred to as runtime exceptions, although in Java, unchecked exceptions include any class that inherits RuntimeException or Error.
  • A runtime exception is defined as the RuntimeException class and its subclasses.
  • Runtime exceptions tend to be unexpected but not necessarily fatal.
  • For example, accessing an invalid array index is unexpected.
  • Even though they do inherit the Exception class, they are not checked exceptions.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

RUNTIME VS. AT THE TIME THE PROGRAM IS RUN

A
  • A runtime (unchecked) exception is a specific type of exception.
  • All exceptions occur at the time that the program is run. (The alternative is compile time, which would be a compiler error.)
  • People don’t refer to them as “run time” exceptions because that would be too easy to confuse with runtime! When you see runtime, it means unchecked. (runtime = unchecked)
  • An unchecked exception can often occur on nearly any line of code, as it is not required to be handled or declared.
  • For example, a NullPointerException can be thrown in the body of the following method if the input reference is null:
void fall(String input) {
    System.out.println(input.toLowerCase());
}
  • We work with objects in Java so frequently, a NullPointerException can happen almost anywhere.
  • If you had to declare unchecked exceptions everywhere, every single method would have that clutter!
  • The code will compile if you declare an unchecked exception. However, it is redundant.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

CHECKED VS. UNCHECKED (RUNTIME) EXCEPTIONS

A

For the exam, you need to know the rules for how checked versus unchecked exceptions function.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

THROWING AN EXCEPTION

A

On the exam, you will see two types of code that result in an exception.
1. The first is code that’s wrong. Here’s an example:

String[] animals = new String[0];
System.out.println(animals[0]);

This code throws an ArrayIndexOutOfBoundsException since the array has no elements.
That means questions about exceptions can be hidden in questions that appear to be about something else.
calls a method on a null reference or that references an invalid array or List index.

2. The second way for code to result in an exception is to explicitly request Java to throw one. Java lets you write statements like these:

throw new Exception();
throw new Exception("Ow! I fell.");
throw new RuntimeException();
throw new RuntimeException("Ow! I fell.");

The throw keyword tells Java you want some other part of the code to deal with the exception.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

THROW VS. THROWS

A

The throw keyword is used as a statement inside a code block to throw a new exception or rethrow an existing exception

throws keyword is used only at the end of a method declaration to indicate what exceptions it supports.

On the exam, you might start reading a long class definition only to realize the entire thing does not compile due to the wrong keyword being used.

Exception e = new RuntimeException();
throw e;

The exception is never instantiated with the new keyword.

throw RuntimeException(); // DOES NOT COMPILE

Since line 4 throws an exception, line 5 can never be reached during runtime. The compiler recognizes this and reports an unreachable code error.

3: try {
4: throw new RuntimeException();
5: throw new ArrayIndexOutOfBoundsException(); // DOES NOT COMPILE
6: } catch (Exception e) {
7: }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Types of exceptions and errors

A

The types of exceptions are important.
Remember that a Throwable is either an Exception or an Error. You should not catch Throwable directly in your code.

  1. Runtime exception,
    • Subclass of RuntimeException,
    • ok for program to catch
    • Not required to handle or declare
  2. Checked exception
    • Subclass of Exception but not subclass of RuntimeException
    • ok for program to catch
    • Required to handle or declare
  3. Error
    • Subclass of Error
    • Not ok for program to catch
    • Not Required to handle or declare
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Recognizing Exception Classes

A

You need to recognize three groups of exception classes for the exam:

  • RuntimeException,
  • checked Exception,
  • and Error.

For the exam, you’ll need to recognize which type of an exception it is and whether it’s thrown by the Java virtual machine (JVM) or a programmer.

For some exceptions, you also need to know which are inherited from one another.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

RuntimeException CLASSES

A

RuntimeException and its subclasses are unchecked exceptions that don’t have to be handled or declared. They can be thrown by the programmer or by the JVM. Common RuntimeException classes include the following:

  1. ArithmeticException
    Thrown when code attempts to divide by zero
  2. ArrayIndexOutOfBoundsException
    Thrown when code uses an illegal index to access an array
  3. ClassCastException
    Thrown when an attempt is made to cast an object to a class of which it is not an instance
  4. NullPointerException
    Thrown when there is a null reference where an object is required
  5. IllegalArgumentException
    Thrown by the programmer to indicate that a method has been passed an illegal or inappropriate argument
  6. NumberFormatException
    Subclass of IllegalArgumentException thrown when an attempt is made to convert a string to a numeric type but the string doesn’t have an appropriate format
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

ArithmeticException

A

Trying to divide an int by zero gives an undefined result. When this occurs, the JVM will throw an ArithmeticException :

int answer = 11 / 0;

Running this code results in the following output:
Exception in thread "main" java.lang.ArithmeticException: / by zero

The thread “main” is telling you the code was called directly or indirectly from a program with a main method. On the exam, this is all the output you will see. Next comes the name of the exception, followed by extra information (if any) that goes with the exception.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

ArrayIndexOutOfBoundsException

A

You know by now that array indexes start with 0 and go up to 1 less than the length of the array—which means this code will throw an ArrayIndexOutOfBoundsException:

int[] countsOfMoose = new int[3];
System.out.println(countsOfMoose[-1]);

This is a problem because there’s no such thing as a negative array index.
Running this code yields the following output:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
Index -1 out of bounds for length 3

At least Java tells us what index was invalid. Can you see what’s wrong with this one?

int total = 0;
int[] countsOfMoose = new int[3];
for (int i = 0; i <= countsOfMoose.length; i++)
total += countsOfMoose[i];

The problem is that the for loop should have < instead of <=. On the final iteration of the loop, Java tries to call countsOfMoose[3], which is invalid. The array includes only three elements, making 2 the largest possible index. The output looks like this:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 
Index 3 out of bounds for length 3
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

ClassCastException

A

Java tries to protect you from impossible casts. This code doesn’t compile because Integer is not a subclass of String:

String type = "moose";
Integer number = (Integer) type; // DOES NOT COMPILE

More complicated code thwarts Java’s attempts to protect you. When the cast fails at runtime, Java will throw a ClassCastException:

String type = "moose";
Object obj = type;
Integer number = (Integer) obj;

The compiler sees a cast from Object to Integer. This could be okay. The compiler doesn’t realize there’s a String in that Object. When the code runs, it yields the following output:

Exception in thread "main" java.lang.ClassCastException:
java.base/java.lang.String
cannot be cast to java.lang.base/java.lang.Integer

Java tells you both types that were involved in the problem, making it apparent what’s wrong.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

NullPointerException

A

Instance variables and methods must be called on a non-null reference. If the reference is null, the JVM will throw a NullPointerException.
It’s usually subtle, such as in the following example, which checks whether you remember instance variable references default to null:

String name;
public void printLength() {
    System.out.println(name.length());
}

Running this code results in this output:

Exception in thread "main" java.lang.NullPointerException
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

IllegalArgumentException

A

IllegalArgumentException is a way for your program to protect itself. You first saw the following setter method in the Swan class in Chapter 7, “Methods and Encapsulation.”

6: public void setNumberEggs(int numberEggs) { // setter
7:     if (numberEggs >= 0) // guard condition
8:         this.numberEggs = numberEggs;
9: }

This code works, but you don’t really want to ignore the caller’s request when they tell you a Swan has –2 eggs. You want to tell the caller that something is wrong—preferably in an obvious way that the caller can’t ignore so that the programmer will fix the problem. Exceptions are an efficient way to do this. Seeing the code end with an exception is a great reminder that something is wrong:

public void setNumberEggs(int numberEggs) {
if (numberEggs < 0)
throw new IllegalArgumentException(
"# eggs must not be negative");
this.numberEggs = numberEggs;
}

The program throws an exception when it’s not happy with the parameter values. The output looks like this:

Exception in thread "main"
java.lang.IllegalArgumentException: # eggs must not be negative

Clearly this is a problem that must be fixed if the programmer wants the program to do anything useful.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

NumberFormatException

A

Java provides methods to convert strings to numbers. When these are passed an invalid value, they throw a NumberFormatException. The idea is similar to IllegalArgumentException. Since this is a common problem, Java gives it a separate class. In fact, NumberFormatException is a subclass of IllegalArgumentException. Here’s an example of trying to convert something non-numeric into an int:

Integer.parseInt("abc");

The output looks like this:
~~~
Exception in thread “main”
java.lang.NumberFormatException: For input string: “abc”
~~~
For the exam, you need to know that NumberFormatException is a subclass of IllegalArgumentException. We’ll cover more about why that is important later in the chapter.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

CHECKED EXCEPTION CLASSES

A

Checked exceptions have Exception in their hierarchy but not RuntimeException. They must be handled or declared. Common checked exceptions include the following:

  1. IOException
    Thrown programmatically when there’s a problem reading or writing a file
  2. FileNotFoundException
    Subclass of IOException thrown programmatically when code tries to reference a file that does not exist

For the exam, you need to know that these are both checked exceptions. You also need to know that FileNotFoundException is a subclass of IOException. You’ll see shortly why that matters.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

ERROR CLASSES

A

Errors are unchecked exceptions that extend the Error class. They are thrown by the JVM and should not be handled or declared. Errors are rare, but you might see these:
1. ExceptionInInitializerError
Thrown when a static initializer throws an exception and doesn’t handle it
2. StackOverflowError
Thrown when a method calls itself too many times (This is called infinite recursion because the method typically calls itself without end.)
3. NoClassDefFoundError
Thrown when a class that the code uses is available at compile time but not runtime

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

ExceptionInInitializerError

A

Java runs static initializers the first time a class is used. If one of the static initializers throws an exception, Java can’t start using the class. It declares defeat by throwing an ExceptionInInitializerError. This code throws an ArrayIndexOutOfBounds in a static initializer:

static {
    int[] countsOfMoose = new int[3];
    nt num = countsOfMoose[-1];
}
public static void main(String... args) { }

This code yields information about the error and the underlying exception:

Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.ArrayIndexOutOfBoundsException: -1 out of bounds for length 3

When executed, you get an ExceptionInInitializerError because the error happened in a static initializer. That information alone wouldn’t be particularly useful in fixing the problem. Therefore, Java also tells you the original cause of the problem: the ArrayIndexOutOfBoundsException that you need to fix. The ExceptionInInitializerError is an error because Java failed to load the whole class. This failure prevents Java from continuing.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Q

StackOverflowError

A

When Java calls methods, it puts parameters and local variables on the stack. After doing this a very large number of times, the stack runs out of room and overflows. This is called a StackOverflowError. Most of the time, this error occurs when a method calls itself.

public static void doNotCodeThis(int num) {
doNotCodeThis(1);
}

The output contains this line:

Exception in thread "main" java.lang.StackOverflowError

Since the method calls itself, it will never end. Eventually, Java runs out of room on the stack and throws the error. This is called infinite recursion. It is better than an infinite loop because at least Java will catch it and throw the error. With an infinite loop, Java just uses all your CPU until you can kill the program.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
26
Q

NoClassDefFoundError

A

A NoClassDefFoundError occurs when Java can’t find the class at runtime. Generally, this means a library available when the code was compiled is not available when the code is executed.

27
Q

Handling Exceptions

A
28
Q

USING TRY AND CATCH STATEMENTS

A
try {
    // Protected code
} catch (expection_type identifier) {
    // Exception handler
}
  1. The try keyword
  2. Curly braces are required.
  3. The catch keyword
  4. the type of exception being caught
  5. the identifier of the exception object
  • The code in the try block is run normally.
  • If any of the statements throws an exception that can be caught by the exception type listed in the catch block,
  • the try block stops running and execution goes to the catch statement.
  • If none of the statements in the try block throws an exception that can be caught, the catch clause is not run.
  • You probably noticed the words block and clause used interchangeably.
  • The exam does this as well, so get used to it. Both are correct.
  • Block is correct because there are braces present.
  • Clause is correct because they are part of a try statement.
  • There aren’t a ton of syntax rules here.
  • The curly braces are required for the try and catch blocks.
29
Q
3: void explore() {
4: try {
5:     fall();
6:     System.out.println("never get here");
7: } catch (RuntimeException e) {
8:     getUp();
9: }
10: seeAnimals();
11: }
12: void fall() { throw new RuntimeException(); }
A
  • First, line 5 calls the fall() method.
  • Line 12 throws an exception.
  • This means Java jumps straight to the catch block, skipping line 6. The girl gets up on line 8.
  • Now the try statement is over, and execution proceeds normally with line 10.
30
Q
try // DOES NOT COMPILE
fall();
catch (Exception e)
System.out.println("get up");
A

The problem is that the braces {} are missing. It needs to look like this:

try {
    fall();
} catch (Exception e) {
    System.out.println("get up");
}

The try statements are like methods in that the curly braces are required even if there is only one statement inside the code blocks, while if statements and loops are special and allow you to omit the curly braces.

31
Q
try { // DOES NOT COMPILE
fall();
}
A
  • This code doesn’t compile because the try block doesn’t have anything after it.
  • Remember, the point of a try statement is for something to happen if an exception is thrown. Without another clause, the try statement is lonely.
  • As you will see shortly, there is a special type of try statement that includes an implicit finally block, although the syntax for this is quite different from this example.
32
Q

CHAINING CATCH BLOCKS

A

A rule exists for the order of the catch blocks. Java looks at them in the order they appear. If it is impossible for one of the catch blocks to be executed, a compiler error about unreachable code occurs. For example, this happens when a superclass catch block appears before a subclass catch block. Remember, we warned you to pay attention to any subclass exceptions.

class AnimalsOutForAWalk extends RuntimeException { }
class ExhibitClosed extends RuntimeException { }
class ExhibitClosedForLunch extends ExhibitClosed { }
public void visitPorcupine() {
    try {
        seeAnimal();
    } catch (AnimalsOutForAWalk e) { // first catch block
        System.out.print("try back later");
    } catch (ExhibitClosed e) { // second catch block
        System.out.print("not today");
    }
}
public void visitMonkeys() {
    try {
        seeAnimal();
    } catch (ExhibitClosedForLunch e) { // subclass exception
        System.out.print("try back later");
    } catch (ExhibitClosed e) { // superclass exception
        System.out.print("not today");
    }
}
public void visitMonkeys() {
    try {
        seeAnimal();
    } catch (ExhibitClosed e) {
        System.out.print("not today");
    } catch (ExhibitClosedForLunch e) { // DOES NOT COMPILE
        System.out.print("try back later");
    }
}

This time, if the more specific ExhibitClosedForLunch exception is thrown, the catch block for ExhibitClosed runs—which means there is no way for the second catch block to ever run. Java correctly tells you there is an unreachable catch block.

33
Q
public void visitSnakes() {
    try {
    } catch (IllegalArgumentException e) {
    } catch (NumberFormatException e) { // DOES NOT COMPILE
    }
}
A

Remember we said earlier you needed to know that NumberFormatException is a subclass of
IllegalArgumentException? This example is the reason why. Since NumberFormatException is a subclass, it will always be caught by the first catch block, making the second catch block unreachable code that does not compile. Likewise, for the exam you need to know that FileNotFoundException is subclass of IOException and cannot be used in a similar manner.

34
Q
public void visitManatees() {
    try {
    } catch (NumberFormatException e1) {
        System.out.println(e1);
    } catch (IllegalArgumentException e2) {
        System.out.println(e1); // DOES NOT COMPILE
    }
}
A
  • To review multiple catch blocks, remember that at most one catch block will run, and it will be the first catch block that can handle it.
  • Also, remember that an exception defined by the catch statement is only in scope for that catch block.
  • the example causes a compiler error since it tries to use the exception class outside the block for which it was defined.
35
Q

APPLYING A MULTI-CATCH BLOCK

A
public static void main(String args[]) {
    try {
        System.out.println(Integer.parseInt(args[1]));
    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Missing or invalid input");
    } catch (NumberFormatException e) {
        System.out.println("Missing or invalid input");
    }
}

reduce the duplicate code
A multi-catch block allows multiple exception types to be caught by the same catch block.

public static void main(String[] args) {
    try {
        System.out.println(Integer.parseInt(args[1])); 
    } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
        System.out.println("Missing or invalid input");
    }
}

Remember that the exceptions can be listed in any order within the catch clause. However, the variable name must appear only once and at the end.

catch(Exception1 e | Exception2 e | Exception3 e) // DOES NOT COMPILE
catch(Exception1 e1 | Exception2 e2 | Exception3 e3) // DOES NOT COMPILE
catch(Exception1 | Exception2 | Exception3 e)
36
Q
try {
    throw new IOException();
} catch (FileNotFoundException | IOException p) {} // DOES NOT COMPILE
A

Specifying it in the multi-catch is redundant, and the compiler gives a message such as this:

The exception FileNotFoundException is already caught by the alternative
IOException

Since FileNotFoundException is a subclass of IOException, this code will not compile. A multi-catch block follows similar rules as chaining catch blocks together that you saw in the previous section. For example, both trigger compiler errors when they encounter unreachable code or duplicate exceptions being caught. The one difference between multi-catch blocks and chaining catch blocks is that order does not matter for a multi-catch block within a single catch expression.

try {
    throw new IOException();
} catch (IOException e) { }
37
Q
11: public void doesNotCompile() { // METHOD DOES NOT COMPILE
12: try {
13: mightThrow();
14: } catch (FileNotFoundException | IllegalStateException e) {
15: } catch (InputMismatchException e | MissingResourceException e) {
16: } catch (FileNotFoundException | IllegalArgumentException e) {
17: } catch (Exception e) {
18: } catch (IOException e) {
19: }
20: }
21: private void mightThrow() throws DateTimeParseException, IOException { }
A

This code is just swimming with errors. In fact, some errors hide others, so you might not see them all in the compiler. Once you start fixing some errors, you’ll see the others. Here’s what’s wrong:

  • Line 15 has an extra variable name. Remember that there can be only one exception variable per catch block.
  • Line 16 cannot catch FileNotFoundException because that exception was already caught on line 14. You can’t list the same exception type more than once in the same try statement, just like with “regular” catch blocks.
  • Lines 17 and 18 are reversed. The more general superclasses must be caught after their subclasses. While this doesn’t have anything to do with multi-catch, you’ll see “regular” catch block problems mixed in with multi-catch.
38
Q

ADDING A FINALLY BLOCK

A
try {
    // Protected code
} catch (expection_type identifier) {
    // Exception handler
} finally {
    // finally block
}
  • The catch block is optional when finally is used
  • The finally keyword
  • The finally block always executes, whether or not an exception occurs.
  • Code does not compile if catch and finally block in wrong order
  • Code does not compile if try statement do not have a catch or finally block.
  • The catch block is not required if finally is present.
39
Q
12: int goHome() {
13: try {
14: // Optionally throw an exception here
15: System.out.print("1");
16: return -1;
17: } catch (Exception e) {
18: System.out.print("2");
19: return -2;
20: } finally {
21: System.out.print("3");
22: return -3;
23: }
24: }
A

There is one additional rule you should know for finally blocks. If a try statement with a finally block is entered, then the finally block will always be executed, regardless of whether the code completes successfully.

  • If an exception is not thrown on line 14, then the line 15 will be executed, printing 1.
  • Before the method returns, though, the finally block is executed, printing 3.
  • If an exception is thrown, then lines 15–16 will be skipped, and lines 17–19 will be executed, printing 2, followed by 3 from the finally block.
  • While the first value printed may differ, the method always prints 3 last since it’s in the finally block.
  • What is the return value of the goHome() method? In this case, it’s always -3. Because the finally block is executed shortly before the method completes, it interrupts the return statement from inside both the try and catch blocks.
40
Q
31: } finally {
32: info.printDetails();
33: System.out.print("Exiting");
34: return "zoo";
35: }
A
  • If info is null, then the finally block would be executed, but it would stop on line 32 and throw a NullPointerException.
  • Lines 33–34 would not be executed.
  • In this example, you see that while a finally block will always be executed, it may not finish.
41
Q

SYSTEM.EXIT()

A

There is one exception to “the finally block always be executed” rule:
Java defines a method that you call as System.exit(). It takes an integer parameter that represents the error code that gets returned.

try {
    System.exit(0);
} finally {
    System.out.print("Never going to get here"); // Not printed
}

System.exit() tells Java, “Stop. End the program right now. Do not pass go. Do not collect $200.”
When System.exit() is called in the try or catch block, the finally block does not run.

42
Q

FINALLY CLOSING RESOURCES

A

files, databases, and various connection objects
these external data sources are referred to as resources.
In many cases, you open a connection to the resource
then read/write the data
Finally, you close the resource to indicate you are done with it.

resource leak if you don’t close a resource
when a program fails to release its connections to a resource, resulting in the resource becoming inaccessible.

4: public void readFile(String file) {
5: FileInputStream is = null;
6: try {
7: is = new FileInputStream("myfile.txt");
8: // Read file data
9: } catch (IOException e) {
10: e.printStackTrace();
11: } finally {
12: if(is != null) {
13: try {
14: is.close();
15: } catch (IOException e2) {
16: e2.printStackTrace();
17: }
18: }
19: }
20: }
43
Q

To solve this, Java includes the try-with-resources statement to automatically close all resources opened in a try clause. This feature is also known as automatic resource management, because Java automatically takes care of the closing.

A
4: public void readFile(String file) {
5: try (FileInputStream is = new FileInputStream("myfile.txt")) {
6: // Read file data
7: } catch (IOException e) {
8: e.printStackTrace();
9: }
10: }

by using a try-with-resources statement, we guarantee that as soon as a connection passes out of scope, Java will attempt to close it within the same method.

44
Q

IMPLICIT FINALLY BLOCKS

A

Behind the scenes, the compiler replaces a try-with-resources block with a try and finally block. We refer to this “hidden” finally block as an implicit finally block since it is created and used by the compiler automatically. You can still create a programmer-defined finally block
when using a try-with-resources statement; just be aware that the implicit one will be called first.

45
Q

Basics of Try-with-Resources

A
  • one or more resources can be opened in the try clause.
  • When there are multiple resources opened, they are closed in the reverse order from which they were created.
  • parentheses are used to list those resources, and semicolons are used to separate the declarations.
try (FileInputStream in = new FileInputStream("data.txt"); 
FileOutputStream out = new FileOutputStream("output");) {
// Protected code
}
  • Any resources that should automatically be closed (in parentheses)
  • Required semicolon between resource declarations
  • Last semicolon is optional (usually omitted)
  • Resources are closed at this point (end of try statement).
46
Q
4: public void readFile(String file) throws IOException {
5: try (FileInputStream is = new FileInputStream("myfile.txt")) {
6: // Read file data
7: }
8: }
A

try statement must have one or more catch blocks or a finally block.
This is still true. The finally clause exists implicitly. You just don’t have to type it.

47
Q

> [!NOTE]
Remember that only a try-with-resources statement is permitted to omit both the catch and finally blocks.
A traditional try statement must have either or both.
You can easily distinguish between the two by the presence of parentheses, (), after the try keyword.

A
48
Q
try (FileInputStream in = new FileInputStream("data.txt"); 
FileOutputStream out = new FileOutputStream("output");) {
    // Protected code
} catch (IOException e) {
    // Exception handler
} finally
    // finally block
}
  • Any resources that should automatically be closed (in perenthese)
  • Resources are closed at this point (end of try statement)
  • Optional catch and finally clauses
A
  • try-with-resources statement is still allowed to have catch and/or finally blocks.
  • In fact, if the code within the try block throws a checked exception not declared by the method in which it is defined or handled by another try/catch block, then it will need to be handled by the catch block.
  • Also, the catch and finally blocks are run in addition to the implicit one that closes the resources.
  • For the exam, you need to know that the implicit finally block runs before any programmer-coded ones.
49
Q

Legal vs. illegal configurations with a traditional try
statement

A

Illegal
1. No catch and finally statement
2. More than 1 finally statement

Legal
1. 1 finally statement
2. 1 or more catch statement
3. 1 finaly and 1 or more catch statement

50
Q

Legal vs. illegal configurations with a
try-with-resources statement

A

Illegal
1. More than 1 finally statement

Legal
1. No catch and finally statement
2. 1 finally statement
2. 1 or more catch statement
3. 1 finaly and 1 or more catch statement

51
Q

AUTOCLOSEABLE

A
  • You can’t just put any random class in a try-with-resources statement.
  • Java requires classes used in a try-with-resources implement the AutoCloseable interface, which includes a void close() method.
52
Q

Declaring Resources

A
  • try-with-resources does support declaring multiple variables, each variable must be declared in a separate statement.
  • Each resource must include the data type and be separated by a semicolon (;).
  • You can declare a resource using var as the data type in a try-with-resources statement, since resources are local variables.
try (MyFileClass is = new MyFileClass(1), // DOES NOT COMPILE
os = new MyFileClass(2)) {
}

does not compile because it is missing the data type and it uses a comma (,) instead of a semicolon (;).

try (MyFileClass ab = new MyFileClass(1), // DOES NOT COMPILE
MyFileClass cd = new MyFileClass(2)) {
}

does not compile because it also uses a comma (,) instead of a semicolon (;)

try (var f = new BufferedInputStream(new FileInputStream("it.txt"))) {
// Process file
}
53
Q

Scope of Try-with-Resources

A
  • The resources created in the try clause are in scope only within the try block.
  • This is another way to remember that the implicit finally runs before any catch/finally blocks that you code yourself.
  • The implicit close has run already, and the resource is no longer available.
3: try (Scanner s = new Scanner(System.in)) {
4: s.nextLine();
5: } catch(Exception e) {
6: s.nextInt(); // DOES NOT COMPILE
7: } finally {
8: s.nextInt(); // DOES NOT COMPILE
9: }
  • The problem is that Scanner has gone out of scope at the end of the try clause. Lines 6 and 8 do not have access to it.
  • This is actually a nice feature. You can’t accidentally use an object that has been closed.
54
Q

You’ve learned two new rules for the order in which code runs in a try-with-resources statement:

A
  • Resources are closed after the try clause ends and before any catch/finally clauses.
  • Resources are closed in the reverse order from which they were created.
55
Q

Following Order of Operation

A

First, we define a custom class that you can use with a try-with-resources statement, as it
implements AutoCloseable.

public class MyFileClass implements AutoCloseable {
    private final int num;
    public MyFileClass(int num) { this.num = num; }
    public void close() {
        System.out.println("Closing: " + num);
    }
}
public static void main(String... xyz) {
    try (MyFileClass a1 = new MyFileClass(1);
        MyFileClass a2 = new MyFileClass(2)) {
        throw new RuntimeException();
    } catch (Exception e) {
        System.out.println("ex");
    } finally {
        System.out.println("finally");
    }
}

The output is as follows:

Closing: 2
Closing: 1
ex
finally
56
Q

TRY-WITH-RESOURCES GUARANTEES

A

Does a try-with-resources statement guarantee a resource will be closed?

the short answer is “no.”

  • The try-with-resources statement guarantees only the close() method will be called.
  • If the close() method encounters an exception of its own or the method is implemented poorly, a resource leak can still occur.
57
Q

THROWING ADDITIONAL EXCEPTIONS

A

What happens when an exception is thrown inside of a catch or finally block?

16: public static void main(String[] a) {
17:     FileReader reader = null;
18:     try {
19:         reader = read();
20:     } catch (IOException e) {
21:         try {
22:             if (reader != null) reader.close();
23:         } catch (IOException inner) {
24:         }
25:     }
26: }
27: private static FileReader read() throws IOException {
28: // CODE GOES HERE
29: }
58
Q
30: public String exceptions() {
31:     StringBuilder result = new StringBuilder();
32:     String v = null;
33:     try {
34:         try {
35:             result.append("before_");
36:             v.length();
37:             result.append("after_");
38:         } catch (NullPointerException e) {
39:             result.append("catch_");
40:             throw new RuntimeException();
41:         } finally {
42:             result.append("finally_");
43:             throw new Exception();
44:         }
45:     } catch (Exception e) {
46:         result.append("done");
47:     }
48:     return result.toString();
49: }
A

The correct answer is before_catch_finally_done.

  • First on line 35, “before_ is added.
  • Line 36 throws a NullPointerException.
  • Line 37 is skipped as Java goes straight to the catch block.
  • Line 38 does catch the exception, and “catch_ is added on line 39.
  • Then line 40 throws a RuntimeException.
  • The finally block runs after the catch regardless of whether an exception is thrown; it adds “finally_ to result. At this point, we have completed the inner try statement that ran on lines 3444.
  • The outer catch block then sees an exception was thrown and catches it on line 45; it adds “done” to result.
59
Q

Calling Methods That Throw Exceptions

A
class NoMoreCarrotsException extends Exception {}
    public class Bunny {
        public static void main(String[] args) {
            eatCarrot(); // DOES NOT COMPILE
        }
    private static void eatCarrot() throws NoMoreCarrotsException {
    }
}
  • The problem is that NoMoreCarrotsException is a checked exception.
  • Checked exceptions must be handled or declared.
  • The code would compile if you changed the main() method to either of these:

declared:
~~~
public static void main(String[] args) throws NoMoreCarrotsException { // declare exception
eatCarrot();
}
~~~

handled
~~~
public static void main(String[] args) {
try {
eatCarrot();
} catch (NoMoreCarrotsException e ) { // handle exception
System.out.print(“sad rabbit”);
}
}
~~~

60
Q
public void bad() {
    try {
        eatCarrot();
    } catch (NoMoreCarrotsException e ) { // DOES NOT COMPILE
        System.out.print("sad rabbit");
    }
}
public void good() throws NoMoreCarrotsException {
    eatCarrot();
}
private void eatCarrot() { }
A
  • Java knows that eatCarrot() can’t throw a checked exception—
  • which means there’s no way for the catch block in bad() to be reached.
  • In comparison, good() is free to declare other exceptions.
61
Q

> [!NOTE]
When you see a checked exception declared inside a catch block on the exam, check and make sure the code in the associated try block is capable of throwing the exception or a subclass of the exception.
If not, the code is unreachable and does not compile.
Remember that this rule does not extend to unchecked exceptions or exceptions declared in a method signature.

A
62
Q

DECLARING AND OVERRIDING METHODS WITH EXCEPTIONS

A

When a class overrides a method from a superclass or implements a method from an interface, it’s not allowed to add new checked exceptions to the method signature.

class CanNotHopException extends Exception { }
class Hopper {
    public void hop() { }
}
class Bunny extends Hopper {
    public void hop() throws CanNotHopException { } // DOES NOT COMPILE
}

An overridden method in a subclass is allowed to declare fewer exceptions than the superclass or interface. This is legal because callers are already handling them.

class Hopper {
    public void hop() throws CanNotHopException { }
}
class Bunny extends Hopper {
    public void hop() { }
}

An overridden method not declaring one of the exceptions thrown by the parent method is similar to the method declaring it throws an exception that it never actually throws. This is perfectly legal.

a class is allowed to declare a subclass of an exception type. The idea is the same. The superclass or interface has already taken care of a broader type. Here’s an example:

class Hopper {
    public void hop() throws Exception { }
}
class Bunny extends Hopper {
    public void hop() throws CanNotHopException { }
}

This rule applies only to checked exceptions. The following code is legal because it has an unchecked exception in the subclass’s version:

class Hopper {
    public void hop() { }
}
class Bunny extends Hopper {
    public void hop() throws IllegalStateException { }
}
63
Q

PRINTING AN EXCEPTION

A

There are three ways to print an exception.

5: public static void main(String[] args) {
6:     try {
7:         hop();
8:     } catch (Exception e) {
9:         System.out.println(e); // 1
10:       System.out.println(e.getMessage()); // 2
11:       e.printStackTrace(); // 3
12:   }
13: }
14: private static void hop() {
15:    throw new RuntimeException("cannot hop");
16: }

output:

java.lang.RuntimeException: cannot hop
cannot hop
java.lang.RuntimeException: cannot hop
at Handling.hop(Handling.java:15)
at Handling.main(Handling.java:7)
64
Q

WHY SWALLOWING EXCEPTIONS IS BAD

A
public static void main(String... p) {
    String textInFile = null;
    try {
        textInFile = readInFile();
    } catch (IOException e) {
        // ignore exception
    }
    // imagine many lines of code here
    System.out.println(textInFile.replace(" ", ""));
}
private static String readInFile() throws IOException {
    throw new IOException();
}

The code results in a NullPointerException. Java doesn’t tell you anything about the original IOException because it was handled. Granted, it was handled poorly, but it was handled.