780 likes | 922 Views
Java II. Chapter 14 Exception Handling. “If anything can go wrong, it will.â€. 14.1 Introduction: definition of terms. • What is an “Exceptionâ€?. exception An event during program execution that prevents the program from continuing normally. Generally, an error. 14.1 Introduction.
E N D
Chapter 14 Exception Handling “If anything can go wrong, it will.”
14.1 Introduction: definition of terms • What is an “Exception”? • exception • An event during program execution that prevents the program from continuing normally. • Generally, an error.
14.1 Introduction • Other languages react to errors by crashing. • Java manages errors in a controlled way. • Java permits recovery, if at all possible.
14.1 Introduction: user expectations • What users expect when an error happens: —tell them an error happened —save all their work-in-progress, if possible. —allow them to exit the program gracefully.
14.1 Introduction: Overview of Java’s Approach • In Java, when an error happens, we say an exception has been thrown. • Once an exception has been thrown, the JVM begins a searchfor some logic able to handle the exception.
14.1 Introduction: Overview of Java’s Approach • The bit of logic able to handle the exception is called, naturally, an exception handler. • When the JVM finds the right exception handler, we say the exception has been caught. • Control is then transferred to the “catching block.”
14.1 Introduction: Who Can Throw An Exception • The exceptioncan be thrownby the Java Virtual Machine—independent of the programmer’s control—or … • the programmer herself canthrow the error, in response to some problem.
14.1 Introduction • Understand, exception handling is really a kind of Control Flow, akin to the ‘if’ and ‘switch’ statements. • The rationale is this: you want to avoid cluttering up your program with logic to handle errors. • So, you move the error-handling logic off to a separate place.
14.1 Introduction: Error Handling Sequence i.) Program is executing. ii.) Something goes wrong—i.e., zero division. iii.) JVM creates anExceptionobject. iv.) TheExceptionobject contains information about the exception that occurred. v.) The Exceptionobject is sent up the line until it encounters someone who cancatch it. The possible "someones" who can handle the exception are the methods in the call stack above where the error occurred.
14.1 Introduction: the Exception Object • Question: What is anExceptionobject? • Answer: An instance of the classThrowable. • What makes something an instance of the classThrowable? • Answer: Any class that extends the class Throwable, or whose Superclass extends that class.
14.1 Introduction: throwable • Objects that are instances of throwable—which means they subclass it (if an interface) or implement (if a class)—are eligible to be thrown by the JVM in response to an error. • After an exception, the JVM works backwards up the chain [stack] of method calls, until it encounters a “handler” for the exception—or a Superclass of the exception—whichever it encounters first.
14.1 Introduction: the call stack • This process of working back up the chain looking for a handler is described this way: “Exceptions propagate error reporting up the call stack of methods.”
14.1 Introduction: definition • What constitutes a “handler” for a particular exception? exception handler A block of code that reacts to a specific type of exception. If the program can recover from the exception, the program will resume executing after the exception handler has executed.
When To Use Exception Handling
14.2 When to Use Exception Handling • Warning! Exception handling should only be used for exceptional situations. Your program must try to prevent exceptions—with normal programming techniques—such as bounds checking on arrays or validation of input data. Exception Handling is the last line of defense.
The Classification of Exceptions
The Classification of Exceptions • As we saw, an Exception is always an instance of the interface Throwable. • You should try to prevent and catch all Exceptions, but there is a branch of the class Throwable that you should never attempt to catch: instances of the class Error.
Our starting point, interface Throwable. Throwable Error Exception These describe internal errors and resource exhaustion inside the JVM. These shouldNOT be caught because they are too major. These describe program or user mistakes. These exceptions should be caught.
Throwable Error Exception IOException RuntimeException
Throwable Any other exception occurs because a bad thing beyond your control (such as an I/O error) happened to your otherwise good program. A RuntimeException happens because you made a programming error. Error Exception IOException RuntimeException
• Examples of RuntimeExceptions: —A bad cast. —An out-of-bounds array access. —Attempting to access a null reference pointer. • Examples of NonRuntimeExceptions: —Trying to read past the end of a file. —Trying to open a malformed URL.
try, throw and catch
14.4 The Basics of Java Exception Handling • • Keywords • Java supports exception handling with these keywords: • try, • throw and • catch.
public class NoExceptionHandling { public static void main( String[] args ) { int x = 1, y = 0, z = 0; z = x / y; System.out.println( “x/y = “ + z ); } } Division by zero. This will never print, nor will it tell you why it failed. The program just dies. It has no exception handling.
public class HasExceptionHandling { public static void main( String[] args ) { int x = 1, y = 0, z = 0; try { z = x / y; System.out.println( “Not executed”); } catch( Exception e ) { System.out.println( “Exception!”); } System.out.println( “x/y = “ + z ); } }
public class HasExceptionHandling { public static void main( String[] args ) { int x = 1, y = 0, z = 0; try { z = x / y; System.out.println( “Not executed”); } catch( Exception e ) { System.out.println( “Exception!”); } System.out.println( “x/y = “ + z ); } } Any code you think might throw an exception should be enclosed in a “try” block. When an exception happens, the remainder of thetryblock is abandoned. Variables go out of scope. No return is possible. Every try block must be paired with at least one “catch” block—often more than one. The catch block will be executed only if an exception occurs.
public class HasExceptionHandling { public static void main( String[] args ) { int x = 1, y = 0, z = 0; try { z = x / y; } catch( Exception e ) { System.out.println( “Exception!”); } System.out.println( “x/y = “ + z ); } } The Sequence: i.) A particular exception occurs. ii.) The runtime system generates an exception object that matches the exception that occurred. iii.) Then, the runtime system goes looking for the nearest catch block that can handle that specific type of exception. If the nearest catch block doesn’t match the exception that happened, the runtime looks beyond this method for another catch block. But, in this case, Exception is the Superclass for all exceptions, so it always matches. Exception! x/y = 0
public class HasExceptionHandlingWrongCatch { public static void main( String[] args ) { int x = 1, y = 0, z = 0; try { z = x / y; } catch( NullPointerException e ) { System.out.println( “Exception”); } System.out.println( “x/y = “ + z ); } } In this case, however, the catch block is expecting a different type of exception. So, this catch block doesn’t catch the error. The exception is NOT caught. The program crashes. The next statement after the catch block isnotexecuted.
public class HasExceptionHandling { public static void main( String[] args ) { int x = 1, y = 0, z = 0; try { z = x / y; } catch( NullPointerException npe ) { System.out.println( “Null Exception!”); } catch( DivideByZeroException dbze ) { System.out.println( “DivideByZeroException!” + dbze.toString() ); } System.out.println( “Whoops!” ); } } This one doesn’t match, so it is skipped. This one does match, so it is executed. Since the exception was caught, execution can resume.
14.4 The Basics of Java Exception Handling • Usually, many statements in your try block can cause exceptions and—since you can’t predict which one will pop—you place several different catch blocks after your onetry block. The most specific catch blocks should be listed first and the generic Exception (which is the Superclass to all exceptions) should be listed last.
14.4 The Basics of Java Exception Handling: term • This whole process is known as the: “Termination model of exception handling.” • The place where the exception occurred is the throw point. • After an exception has occurred, execution abandons the try block from the throw point on. • We say the block that threw the exceptionexpires.
The finally Block
The finally Block • Java exception handling offers a third optional twist on the try-catch block: • The finally block offers you a place to put code that must always be executedno matter what—exception or no exception. • Remember: if you use a try, then you must use a catch . • The finally is optional .
The finally Block • The finally block is like the Mafia—if you invite it in your code, it’s there whether you end up needing it or not. • So, if your try block works perfectly—then the code in the finally block gets executed. • And… if your try block throws an exception and the catch block catches the exception—then the code in the finally block still gets executed.
public class HasFinallyBlockToo { public static void main( String[] args ) { int x = 1, y = 0, z = 0; try { z = x / y; } catch( NullPointerException e ) { System.out.println( “Exception”); } finally { System.out.println( “Always!”); } } } Always, Always Always executes!
The try Block: A Net Over a Rabbit Hole
A Net Over a Rabbit Hole • Obviously, a try block can catch an exception in the method where it’s located. • But, a try block can also catch an exception far removed from the method where it’s located—as long as no other block in between catches it first.
public class GenericExceptionHandling { public static void main( String[] args ) { try { // exception XYZ } catch( XYZ e ) { System.out.println( “XYZ Happened”); } } } This is routine exception handling, which should now be familiar.
public class CatchesDistantException { public static void main( String[] args ) { try { MyClass tom = new MyClass(); tom.causesException(); } catch( XYZ e ) { System.out.println( “XYZ Happened”); } } } As long as our catch block is the first one to be encountered, it will catch XYZ exception thrown deep inside of tom.causesException();
A Net Over a Rabbit Hole • Now, we will see a more complex example of the previous example. • We will show how a method call far down the method stack can: —throw an exception and —propagate the exception back up the call stack in search of a handler.
public class AException { public AException() { System.out.println( "Cnst: AException" ); BException be = new BException(); } public static void main(String[] args) { AException ae = new AException(); } } Now, the burgundy arrow will wait with the pink arrow, to show that now two methods are “stacked” up (in the stack) waiting for the execution of their methods to conclude. The pink arrow will stay and wait, to illustrate that this method has not yet finished executing. It has opened another method in the call stack. public class BException { public BException() { System.out.println( "Cnst: BException" ); CException ce = new CException(); try { ce.populateArray(); } catch( ArrayIndexOutOfBoundsException e ) { //do something } } } Now, the red arrow will stay and wait, to illustrate that this method has not yet finished executing. It has opened yet another method in the call stack. BException AException AException.main()
public class CException { int[] intArray = new int[3]; public CException() { System.out.println( "Cnst: CException" ); } public void populateArray() throws ArrayIndexOutOfBoundsException { intArray[0] = 100; intArray[1] = 101; intArray[2] = 102; intArray[3] = 103; } } These are the method calls from the other classes still waiting. BException AException AException.main()
public class AException { public AException() { System.out.println( "Cnst: AException" ); BException be = new BException(); } public static void main(String[] args) { AException ae = new AException(); } } Now, in the try block, we go back to the instance of class CException we just instantiated to execute its method populateArray() public class BException { public BException() { System.out.println( "Cnst: BException" ); CException ce = new CException(); try { ce.populateArray(); } catch( ArrayIndexOutOfBoundsException e ) { //do something } } } Since the red Constructor method of CException finished, this line in the stack trace goes away. BException AException AException.main()
public class CException { int[] intArray = new int[3]; public CException() { System.out.println( "Cnst: CException" ); } public void populateArray() throws ArrayIndexOutOfBoundsException { intArray[0] = 100; intArray[1] = 101; intArray[2] = 102; intArray[3] = 103; } } 100 101 102 ArrayIndexOutOfBoundsException ! These are the method calls from the other classes still waiting. AException AException.main()
public class AException { public AException() { System.out.println( "Cnst: AException" ); BException be = new BException(); } public static void main(String[] args) { AException ae = new AException(); } } After the thrown exception has been successfully caught, the BException() constructor can finish. public class BException { public BException() { System.out.println( "Cnst: BException" ); CException ce = new CException(); try { ce.populateArray(); } catch( ArrayIndexOutOfBoundsException e ) { //do something } } } Since the try block threw an exception, when we propagate out of the called method, the JVM immediately looks for an appropriate catch block. AException AException.main()
public class AException { public AException() { System.out.println( "Cnst: AException" ); BException be = new BException(); } public static void main(String[] args) { AException ae = new AException(); } } And lastly, the AException that started it all can finish and we’re back where we started. Cnst: AException Cnst: BException Cnst: CException Exception: ArrayIndexOutOfBoundsException After method populateArray() s AException.main()
Advisory: although we used the RuntimeExceptionArrayIndexOutOfBoundsException for this example, in fact this is one you should prevent through good old fashioned bounds checking, rather than allowing it to throw an exception. Still, it makes for a good example.
Exception Handling: Limitations
Exception Handling: Limitations • Exception-handling can only cope with synchronous errors—ones that occur in the execution step as it is currently being executed.