Understanding Java Exceptions Outline What exceptions are for

  • Slides: 47
Download presentation
Understanding Java Exceptions

Understanding Java Exceptions

Outline What exceptions are for What exceptions are NOT for Catching & Throwing exceptions

Outline What exceptions are for What exceptions are NOT for Catching & Throwing exceptions Exception Specifications Standard Java Exceptions and Polymorphism The finally clause Resource Management Uncaught Exceptions

What Exceptions are For To handle Bad Things I/O errors, other runtime errors n

What Exceptions are For To handle Bad Things I/O errors, other runtime errors n when a function fails to fulfill its specification n so you can restore program stability (or exit gracefully) n

What Exceptions are For ~ continued ~ To force you to handle Bad Things

What Exceptions are For ~ continued ~ To force you to handle Bad Things because return codes can be tedious n and sometimes you’re lazy n

Example File I/O public File. Reader(String file. Name) throws File. Not. Found. Exception public

Example File I/O public File. Reader(String file. Name) throws File. Not. Found. Exception public void close() throws IOException

import java. io. *; class Open. File { public static void main(String[] args) {

import java. io. *; class Open. File { public static void main(String[] args) { if (args. length > 0) { try { // Open a file: File. Reader f = new File. Reader(args[0]); System. out. println(args[0] + " opened"); f. close(); } catch (IOException x) { System. out. println(x); } }

What Exceptions are For ~ continued ~ To signal errors from constructors n because

What Exceptions are For ~ continued ~ To signal errors from constructors n because constructors have no return value

What Exceptions are NOT For Alternate Returns: n e. g. , when end-of-file is

What Exceptions are NOT For Alternate Returns: n e. g. , when end-of-file is reached: while ((s = f. read. Line()) != null) … Exceptions are only for the exceptional!

Catching Exceptions Wrap code to be checked in a try-block n checking occurs all

Catching Exceptions Wrap code to be checked in a try-block n checking occurs all the way down the execution stack try-blocks can be nested n control resumes at most enclosed matching handler

Catching Exceptions ~ continued ~ Place one or more catch-clauses after tryblock runtime system

Catching Exceptions ~ continued ~ Place one or more catch-clauses after tryblock runtime system looks back up the call stack for a matching handler n subclass types match superclass types n n catching n handlers are checked in the order they appear n place n Exception catches everything (almost) most derived types first! execution resumes after last handler n if you let it (could branch or throw)

Throwing Exceptions Must throw objects derived (ultimately) from Throwable Usually derive from java. lang.

Throwing Exceptions Must throw objects derived (ultimately) from Throwable Usually derive from java. lang. Exception The class name is the most important attribute of an exception Can optionally include a message n Provide two constructors: n n My. Exception( ) My. Exception(String s)

Throwing Exceptions ~ continued ~ Control is passed up the execution stack to a

Throwing Exceptions ~ continued ~ Control is passed up the execution stack to a matching handler Various methods exist for processing exceptions: get. Message( ) n to. String( ) (class name + message) n print. Stack. Trace( ) n

Throwing Exceptions ~ continued ~ Functions must “advertise” their exceptions n every function must

Throwing Exceptions ~ continued ~ Functions must “advertise” their exceptions n every function must specify the “checked” exceptions it (or its callees!) may throw Callers must do one of two things: handle your exceptions with try-catch, or n advertise your exceptions along with theirs n

Sample Program Fixed. Stack implements a stack with an array of Object n various

Sample Program Fixed. Stack implements a stack with an array of Object n various methods throw exceptions n class Stack. Exception n Stack. Test n must handle Stack. Exceptions

class Stack. Exception extends Exception { Stack. Exception() {} } Stack. Exception(String msg) {

class Stack. Exception extends Exception { Stack. Exception() {} } Stack. Exception(String msg) { super(msg); }

class Fixed. Stack { private int capacity; private int size; private Object[] data; public

class Fixed. Stack { private int capacity; private int size; private Object[] data; public Fixed. Stack(int cap) { data = new Object[cap]; capacity = cap; size = 0; } public void push(Object o) throws Stack. Exception { if (size == capacity) throw new Stack. Exception("overflow"); data[size++] = o; }

public Object pop() throws Stack. Exception { if (size <= 0) throw new Stack.

public Object pop() throws Stack. Exception { if (size <= 0) throw new Stack. Exception("underflow"); return data[--size]; } public Object top() throws Stack. Exception { if (size <= 0) throw new Stack. Exception("underflow"); return data[size-1]; } } public int size() { return this. size; }

class Stack. Test { public static void main(String[] args) { Fixed. Stack s =

class Stack. Test { public static void main(String[] args) { Fixed. Stack s = new Fixed. Stack(3); do. Test(s); } public static void do. Test(Fixed. Stack s) { try { System. out. println("Initial size = " + s. size()); s. push("one"); s. push(new Integer(2)); s. push(new Float(3. 0)); s. push("one too many"); } catch(Stack. Exception x) { System. out. println(x); } // error!

try { System. out. println("Top: " + s. top()); System. out. println("Popping. . .

try { System. out. println("Top: " + s. top()); System. out. println("Popping. . . "); while (s. size() > 0) System. out. println(s. pop()); } } } catch(Stack. Exception x) { throw new Internal. Error(x. to. String()); } /* Output: Initial size = 0 Stack. Exception: overflow Top: 3. 0 Popping. . . 3. 0 2 one */

Using print. Stack. Trace( ) catch(Stack. Exception x) { x. print. Stack. Trace(System. out);

Using print. Stack. Trace( ) catch(Stack. Exception x) { x. print. Stack. Trace(System. out); } … Stack. Exception: overflow at Fixed. Stack. push(Fixed. Stack. java: 18) at Stack. Test. do. Test(Stack. Test. java, Compiled Code) at Stack. Test. main(Stack. Test. java: 6)

Standard Java Exceptions Throwable Exception Runtime. Exception Error IOException . . .

Standard Java Exceptions Throwable Exception Runtime. Exception Error IOException . . .

Class java. lang. Exception The one you usually derive from “Checked Exceptions” specifications checked

Class java. lang. Exception The one you usually derive from “Checked Exceptions” specifications checked at compile time n you must either catch or advertise these n Used for recoverable errors n n Not programmer errors

java. lang. Exception Subclasses ~ sample ~ AWTException Class. Not. Found. Exception Clone. Not.

java. lang. Exception Subclasses ~ sample ~ AWTException Class. Not. Found. Exception Clone. Not. Supported. Exception IOException No. Such. Field. Exception

Class java. lang. Error For JVM Failures and other Weird Things n let program

Class java. lang. Error For JVM Failures and other Weird Things n let program terminate Internal. Error is one of these Don’t catch them n you don’t know what to do! These are “unchecked exceptions” n not required to advertise

java. lang. Error Subclasses AWTError Linkage. Error n … Thread. Death Virtual. Machine. Error

java. lang. Error Subclasses AWTError Linkage. Error n … Thread. Death Virtual. Machine. Error n Internal. Error, Out. Of. Memory. Error, Stack. Overflow. Error, Unknown. Error

Class java. lang. Runtime. Exception Stupid Name! n Same as logic_error in C++ Program

Class java. lang. Runtime. Exception Stupid Name! n Same as logic_error in C++ Program logic errors e. g. , bad cast, using a null handle, array index violation, etc. n Shouldn’t happen! n n fixed n during testing Similar in spirit to C’s assert( ) macro n mainly for debugging These are called “unchecked exceptions”

java. lang. Runtime. Exception Subclasses (sample) Arithmetic. Exception (e. g. , divide by 0)

java. lang. Runtime. Exception Subclasses (sample) Arithmetic. Exception (e. g. , divide by 0) Array. Store. Exception Class. Cast. Exception Illegal. Argument. Exception Index. Out. Of. Bounds. Exception Null. Pointer. Exception Unsupported. Operation. Exception

Principle “Use checked exceptions for recoverable conditions and run-time exceptions for programming errors” (Bloch,

Principle “Use checked exceptions for recoverable conditions and run-time exceptions for programming errors” (Bloch, Effective Java)

“Fixing” Fixed. Stack. Exception should be a runtime exception Then the “throws” specifications aren’t

“Fixing” Fixed. Stack. Exception should be a runtime exception Then the “throws” specifications aren’t needed

class Stack. Exception extends Runtime. Exception { Stack. Exception() {} } Stack. Exception(String msg)

class Stack. Exception extends Runtime. Exception { Stack. Exception() {} } Stack. Exception(String msg) { super(msg); } • Then remove all “throws” specifications from Fixed. Stack

Exceptions and Inheritance ~ Subclass Overrides ~ Methods overridden in subclasses must maintain the

Exceptions and Inheritance ~ Subclass Overrides ~ Methods overridden in subclasses must maintain the parent method’s contract substitutability n cannot add exceptions to specification n can omit, however n can throw subclasses of parent’s exceptions n

// Relaxing the Exception Specification class Parent { public void f() throws Exception {}

// Relaxing the Exception Specification class Parent { public void f() throws Exception {} } class Child extends Parent { public void f() // OK! {} } class Override { public static void main(String[] args) { Child c = new Child(); c. f(); } }

// Throwing a Subclass Exception class My. Exception extends Exception {} class Another. Exception

// Throwing a Subclass Exception class My. Exception extends Exception {} class Another. Exception extends My. Exception {} class Parent { public void f() throws My. Exception {} } class Child extends Parent { public void f() throws Another. Exception {} } class Override { public static void main(String[] args) throws Another. Exception { Child c = new Child(); c. f(); } }

Exception-handling Syntax ~ The Whole Picture ~ try { // normal code (conditionally executes)

Exception-handling Syntax ~ The Whole Picture ~ try { // normal code (conditionally executes) } catch (Exception. Type 1 x) { // handle Exception. Type 1 error } … catch (Exception. Type. N x) { // handle Exception. Type. N error } finally { // invariant code ("always" executes) }

The finally Clause For code that must ALWAYS run No matter what! n Even

The finally Clause For code that must ALWAYS run No matter what! n Even if a return or break occurs first n Exception: System. exit( ) n Placed after handlers (if they exist) n try-block must either have a handler or a finally -block

class Finally. Test { public static void f() throws Exception { try { //

class Finally. Test { public static void f() throws Exception { try { // return; // System. exit(0); // throw new Exception(); // // 0 1 2 3 a } catch (Exception x) { // throw new Exception(); // 3 b } finally { System. out. println("finally!"); } } System. out. println("last statement");

} public static void main(String[] args) { try { f(); } catch(Exception x) {}

} public static void main(String[] args) { try { f(); } catch(Exception x) {} }

Program Output 0: finally! last statement 1: finally! 2: (no output) 3 a: same

Program Output 0: finally! last statement 1: finally! 2: (no output) 3 a: same as 0: 3 a + 3 b: compiler error (last statement not reachable)

Managing Resources Other than memory n files, connections, etc. Need to deallocate, even if

Managing Resources Other than memory n files, connections, etc. Need to deallocate, even if exceptions occur Use finally UPDATE: As of Java 7, you can use the trywith-resources statement. https: //www. baeldung. com/java-try-withresources

Try with resources try (Scanner scanner = new Scanner(new File("test. txt"))) { while (scanner.

Try with resources try (Scanner scanner = new Scanner(new File("test. txt"))) { while (scanner. has. Next()) { System. out. println(scanner. next. Line()); } } catch (File. Not. Found. Exception fnfe) { fnfe. print. Stack. Trace(); } From https: //www. baeldung. com/java-try-with-resources

import java. io. *; class Manage { public static void f(String fname) throws IOException

import java. io. *; class Manage { public static void f(String fname) throws IOException { File. Reader f = null; // must define outside try { f = new File. Reader(fname); System. out. println("File opened"); int c = f. read(); // read a byte //. . . } finally { if (f != null) { System. out. println("File closed"); f. close(); // beware lost exception!!! } } }

} public static void main(String[] args) { try { f(args[0]); } catch (Exception x)

} public static void main(String[] args) { try { f(args[0]); } catch (Exception x) { System. out. println(x); } }

Program Output If no file name given (args. length == 0): java. lang. Array.

Program Output If no file name given (args. length == 0): java. lang. Array. Index. Out. Of. Bounds. Exception: 0 If file doesn’t exist: java. io. File. Not. Found. Exception: <file name> If file opened successfully: file opened file closed

When to Handle Exceptions Note: Manage. f( ) didn’t catch anything n wouldn’t know

When to Handle Exceptions Note: Manage. f( ) didn’t catch anything n wouldn’t know what to do if it did! You often let exceptions pass up the call stack Or you can re-throw in a catch throw x; // in a handler where x was caught n or re-throw a new type of exception n

Exception Etiquette Don’t catch what you can’t (at least partially) handle n re-throw if

Exception Etiquette Don’t catch what you can’t (at least partially) handle n re-throw if only partially handled (“catch & release”: if you’re not going to eat it, throw it back!) Don’t catch & ignore n catch (Exception x){} // disables exceptions!

How Exceptions Work When an exception is thrown execution backtracks up the runtime stack

How Exceptions Work When an exception is thrown execution backtracks up the runtime stack (list of active function invocations) Each stack frame contains information regarding local handlers, if any n Otherwise, execution returns up to the next caller, looking for a suitable catch What happens if there isn’t a matching catch?

Uncaught Exceptions What if there is no handler for an exception? The thread dies!

Uncaught Exceptions What if there is no handler for an exception? The thread dies! n exceptions belong to a thread (stack-specific)