32
13: Error Handling with Exceptions The basic philosophy of Java is that "badly formed code will not be run." 1

13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

  • Upload
    others

  • View
    10

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

13: Error Handling with Exceptions

The basic philosophy of Java is that "badly formed code will not be run."

1

Page 2: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

2

Error Handling in Java

C++/Java: Badly-formed code will not compile.

Java: Badly-formed code, if compiled, will not run.

Not all errors can be caught at compile time.

Run-time error handling is integrated into the core of the language and enforced by the compiler.

The standard libraries require the handling of exceptional conditions.

Page 3: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

3

Program logic.

Errors like exceeding array bounds and division by zero can be prevented by the programmer.

Environmental conditions.

Loss of a network connection or a full disk can be anticipated but not prevented.

Sources of Problems

Page 4: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

4

An exception is an object that signals an error condition and provides information about the error.

When an exception is generated, control is passed up the call stack until a specific handler is found.

Multiple handlers for different exceptions may be provided at multiple levels.

In Java, many exceptions cannot be ignored. This is enforced by the compiler.

Exceptions

Page 5: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

5

An exceptional condition is a problem that prevents the continuation of the current method or scope.

To indicate such a condition, one throws an exception object:

Basic Exceptions

or

if (t == null) throw new NullPointerException();

If (t == null) throw new NullPointerException("t = null");

Page 6: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

6

The Exception Class Hierarchy

Throwable

Error Exception

RuntimeException

CheckedExceptions

UncheckedExceptions

Page 7: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

7

Throwable Methodspublic class Throwable implements Serializable { public Throwable(); public Throwable(String message); public Throwable(Throwable cause); public Throwable(String message, Throwable cause); public Throwable getCause(); public String getLocalizedMessage(); public String getMessage(); public StackTraceElement[] getStackTrace(); public void setStackTrace(StackTraceElement[] stackTrace); public Throwable fillInStackTrace(); public Throwable initCause(Throwable cause); public void printStackTrace(); public void printStackTrace(java.io.PrintStream s); public void printStackTrace(java.io.printWriter s); public String toString();}

Page 8: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

8

Exception & RuntimeException

Methodspublic class Exception extends Throwable { public Exception(); public Exception(Throwable cause); public Exception(String message); public Exception(String message, Throwable cause);}

public class RuntimeException extends Exception { public RuntimeException(); public RuntimeException(Throwable cause); public RuntimeException(String message); public RuntimeException(String message, Throwable cause);}

Page 9: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

9

Catching Exceptions

A thrown exception will cause immediate transfer from a try block to an appropriate catch clause.

try { /* Code that might generate exceptions */ }catch (Type1 e1) { /* Handle exceptions of Type1 */ }catch (Type2 e2) { /* Handle exceptions of Type2 */ }catch (Type3 e3) { /* Handle exceptions of Type3 */ }finally { /* Execute code that will always run */ }

Page 10: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

10

The Exception Specification

Any exception thrown by a method (except for runtime exceptions) must be declared in a throws clause.

This is enforced by the compiler.

All checked exceptions will be caught somewhere.

Page 11: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

11

Creating an Exception

Throwing MyException from f()MyException at FullConstructors.f(FullConstructors.java:10) at FullConstructors.main(FullConstructors.java:16)Throwing MyException from g()MyException: Originated in g() at FullConstructors.g(FullConstructors.java:13) at FullConstructors.main(FullConstructors.java:20)

Page 12: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

12

Getting More Creative

class MyException2 extends Exception { private int x; public MyException2() {} public MyException2(String msg) { super(msg); } public MyException2(String msg, int x) { super(msg); this.x = x; } public int val() { return x; } public String getMessage() { return "Detail Message: " + x + " " + super.getMessage(); }}

Page 13: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

13

Testing the Classpublic class ExtraFeatures { public static void f() throws MyException2 { print("Throwing MyException2 from f()"); throw new MyException2(); } public static void g() throws MyException2 { print("Throwing MyException2 from g()"); throw new MyException2("Originated in g()"); } public static void h() throws MyException2 { print("Throwing MyException2 from h()"); throw new MyException2("Originated in h()", 47); } public static void main(String[] args) { try { f(); } catch (MyException2 e) { e.printStackTrace(System.out); } try { g(); } catch (MyException2 e) { e.printStackTrace(System.out); } try { h(); } catch (MyException2 e) { e.printStackTrace(System.out); System.out.println("e.val() = " + e.val()); } }}

Throwing MyException2 from f()MyException2: Detail Message: 0 null at ExtraFeatures.f(ExtraFeatures.java:22) at ExtraFeatures.main(ExtraFeatures.java:34)Throwing MyException2 from g()MyException2: Detail Message: 0 Originated in g() at ExtraFeatures.g(ExtraFeatures.java:26) at ExtraFeatures.main(ExtraFeatures.java:39)Throwing MyException2 from h()MyException2: Detail Message: 47 Originated in h() at ExtraFeatures.h(ExtraFeatures.java:30) at ExtraFeatures.main(ExtraFeatures.java:44)e.val() = 47

Page 14: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

14

RethrowingA caught exception may be partially handled and thrown again:

The rethrown exception goes to the next higher context. All of its contained information is preserved.

catch(Exception e) } System.err.println("An exception was thrown."); throw e; }

Page 15: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

15

Installing a New Stack Tracepublic class Rethrowing { public static void f() throws Exception { System.out.println("originating the exception in f()"); throw new Exception("thrown from f()"); } public static void g() throws Exception { try { f(); } catch (Exception e) { System.out.println("Inside g(),e.printStackTrace()"); e.printStackTrace(System.out); throw e; } } public static void h() throws Exception { try { f(); } catch (Exception e) { System.out.println("Inside h(),e.printStackTrace()"); e.printStackTrace(System.out); throw (Exception)e.fillInStackTrace(); } } public static void main(String[] args) { try { g(); } catch (Exception e) { System.out.println("main: printStackTrace()"); e.printStackTrace(System.out); } try { h(); } catch (Exception e) { System.out.println("main: printStackTrace()"); e.printStackTrace(System.out); } }}

originating the exception in f()Inside g(),e.printStackTrace()java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:7) at Rethrowing.g(Rethrowing.java:11) at Rethrowing.main(Rethrowing.java:29)main: printStackTrace()java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:7) at Rethrowing.g(Rethrowing.java:11) at Rethrowing.main(Rethrowing.java:29)originating the exception in f()Inside h(),e.printStackTrace()java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:7) at Rethrowing.h(Rethrowing.java:20) at Rethrowing.main(Rethrowing.java:35)main: printStackTrace()java.lang.Exception: thrown from f() at Rethrowing.h(Rethrowing.java:24) at Rethrowing.main(Rethrowing.java:35)

Page 16: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

16

Rethrowing a New Exceptionclass OneException extends Exception { public OneException(String s) { super(s); }}

class TwoException extends Exception { public TwoException(String s) { super(s); }}

public class RethrowNew { public static void f() throws OneException { System.out.println("originating the exception in f()"); throw new OneException("thrown from f()"); } public static void main(String[] args) { try { try { f(); } catch (OneException e) { System.out.println( "Caught in inner try, e.printStackTrace()"); e.printStackTrace(System.out); throw new TwoException("from inner try"); } } catch (TwoException e) { System.out.println( "Caught in outer try, e.printStackTrace()"); e.printStackTrace(System.out); } }}

originating the exception in f()Caught in inner try, e.printStackTrace()OneException: thrown from f() at RethrowNew.f(RethrowNew.java:15) at RethrowNew.main(RethrowNew.java:20)Caught in outer try, e.printStackTrace()TwoException: from inner try at RethrowNew.main(RethrowNew.java:25)

Page 17: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

17

Cleanup With Finally

The finally clause provides a mechanism to take care of non-memory resources.

Anything that must always be done should be included in the finally clause.

The finally clause should not be used for operations that may not always be needed or appropriate.

Page 18: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

18

Doesn’t Always Workpublic class Switch { private boolean state = false; public boolean read() { return state; } public void on() { state = true; print(this); } public void off() { state = false; print(this); } public String toString() { return state ? "on" : "off"; }}

public class OnOffSwitch { private static Switch sw = new Switch(); public static void f() throws OnOffException1, OnOffException2 {} public static void main(String[] args) { try { sw.on(); // Code that can throw exceptions... f(); sw.off(); } catch (OnOffException1 e) { System.out.println("OnOffException1"); sw.off(); } catch (OnOffException2 e) { System.out.println("OnOffException2"); sw.off(); } }}

Page 19: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

19

Always Works

public class WithFinally { static Switch sw = new Switch(); public static void main(String[] args) { try { sw.on(); // Code that can throw exceptions... OnOffSwitch.f(); } catch (OnOffException1 e) { System.out.println("OnOffException1"); } catch (OnOffException2 e) { System.out.println("OnOffException2"); } finally { sw.off(); } }}

Page 20: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

20

Inheritance Implications

Overridden methods may only throw exceptions specified in the base-class version.

Derived-class exceptions do not violate the rule.

The restriction does not apply to constructors.

Derived-class constructors must declare base-class exeptions in their exception specification.

Page 21: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

21

If a constructor throws an exception proper cleanup may not occur.

Any sort of cleanup done in a finally clause should be executed conditionally and controlled by a flag.

Only perform this cleanup in finally if you’re forced to.

Constructors

Page 22: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

22

Cleanup Examplepublic class InputFile { private BufferedReader in; public InputFile(String fname) throws Exception { try { in = new BufferedReader(new FileReader(fname)); /* Other code that might throw exceptions */} catch (FileNotFoundException e) { System.out.println("Could not open " + fname); // Wasn't open, so don't close it throw e; } catch (Exception e) { // all other exceptions must close it try { in.close(); } catch (IOException e2) { System.out.println("in.close() unsuccessful"); } throw e; /* Rethrow */ } finally { /* Don't close it here */} }

Page 23: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

23

The Rest of the Class

public String getLine() { String s; try { s = in.readLine(); } catch (IOException e) { throw new RuntimeException("readLine() failed"); } return s; }

public void dispose() { try { in.close(); System.out.println("dispose() successful"); } catch (IOException e2) { throw new RuntimeException("in.close() failed"); } }}

Page 24: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

24

Client Code

public class Cleanup { public static void main(String[] args) { try { InputFile in = new InputFile("Cleanup.java"); try { String s; int i = 1; while ((s = in.getLine()) != null) ; /* Perform line-by-line processing here... */ } catch (Exception e) { System.out.println("Caught Exception in main"); e.printStackTrace(System.out); } finally { in.dispose(); } } catch (Exception e) { System.out.println("InputFile construction failed"); } }}

Page 25: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

25

Exception Matching...

Handlers are searched through in the order in which they were written.Derived-class exceptions match base-class handlers.The compiler will detect unreachable code.

Page 26: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

26

...Exception Matchingclass Annoyance extends Exception {}

class Sneeze extends Annoyance {}

public class Human { public static void main(String[] args) { // Catch the exact type: try { throw new Sneeze(); } catch (Sneeze s) { System.out.println("Caught Sneeze"); } catch (Annoyance a) { System.out.println("Caught Annoyance"); } // Catch the base type: try { throw new Sneeze(); } catch (Annoyance a) { System.out.println("Caught Annoyance"); } }}

Page 27: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

27

Avoiding the IssueExceptions are harmful if swallowed:

Or you can do nothing and get a stack trace:

try { /* ...to do something useful */ }catch(Exception e) {} // Gulp!

public class MainException { public static void main(String[] args) throws Exception { // Use the file... // Close the file: file.close(); }}

Page 28: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

28

Converting an Exception

You can turn a checked exception into a runtime exception:

try { somethingUseful(); }catch(IDontKnowWhatToDoWithThisCheckedException e) { throw new RunTimeException(e); }

Page 29: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

29

Overhead

Exceptions are free as long as they don’t get thrown.

Thrown exceptions are expensive.

Don’t use exceptions for normal flow of control.

Exceptions should only be used to handle abnormal conditions.

Page 30: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

30

Handle an exception only if there is enough information in the current context to correct the error. If not, allow it to propigate upward.

Separated error handling from normal flow makes code more readable and maintainable.

Handle complete tasks, not single statements in a try block.

Resumption causes excessive coupling and is not available in C++/Java. Use loops to retry.

Guidelines

Page 31: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

31

Use exceptions in constructors if something could go wrong: people assume construction succeeds.

If you catch an exception, do something with it; don’t stub it out.

Clean up using finally.

Guidelines

Page 32: 13: Error Handling with Exceptionsgaryb/Courses/Java/Slides/Ch13.pdf · Errors like exceeding array bounds and division ... Don’t use exceptions for normal flow of control. Exceptions

32

Exception handling in Java is enforced by the compiler:

they must be caught,exception specification must be provided.

Error handling is clean and straightforward:error handling is left to the client programmer,how the client handles the error is decoupled from the implementation,the implementer knows that errors will be handled.

If it seems like more work it’s because you’ve been ignoring errors.

Summary