220 likes | 400 Views
Effective Java, Chapter 9: Exceptions. Items 57-65 Last modified Fall 2012 Paul Ammann. Item 57: Use Exceptions only for Exceptional Conditions. Don’t do this! try{ int i=0; while (true) { range[i++].climb(); } }catch(IndexOutOfBoundsException e){}
E N D
Effective Java, Chapter 9: Exceptions Items 57-65 Last modified Fall 2012 Paul Ammann
Item 57: Use Exceptions only for Exceptional Conditions • Don’t do this! try{ int i=0; while (true) { range[i++].climb(); } }catch(IndexOutOfBoundsException e){} • Note that code may hide unrelated exception! • Implications for API design • A well designed API must not force its clients to use exception handling for ordinary flow control • Provide state testing method instead of forcing client to catch exception.
More Item 57 • Do this instead for (Mountain m: range) { m.climb(); } Note: • (implicit) “State Testing” method: i < range.length • No possibility of unintentionally hiding IndexOutOfBoundsException from climb() • Bottom line: Don’t use exceptions for ordinary flow control
More Item 57 • How about? try{ Iterator i = collection.iterator(); while (true) { Foo foo = (Foo) i.next(); ... } }catch(NoSuchElementException e){} • versus: for (Iterator i = collection.iterator(); i.hasNext();){ Foo foo = (Foo) i.next(); ... }
More Item 57 • Two basic options • State testing method • Doesn’t work in concurrent environment • State may change between state test and actual call • May be undesirable if state testing method is as much computation as actual call • Then, it’s better to have a distinguished return value • Distinguished return value • May not be an unused special value • Example: “null” for Object return types • Iterator next() method can legitimately return “null” • Faulty use of distinguished return value model harder to detect
Item 58: Checked vs. Unchecked • Unchecked exceptions indicate programming errors • Precondition violations • Recovery is impossible • Checked exceptions indicate recoverable conditions • Force the caller to handle the exception
More Item 58 • Use unchecked exceptions if • client has nothing to do • OutOfMemoryException • client knows better • doesn’t need try-catch block; if-then block would suffice. • Use checked exceptions if client has some reasonable action • IOException Calling code is correct, but exception can still be raised!
Item 59: Avoid Unnecessary Use of Checked Exceptions try{ obj.action(args) }catch(SomeCheckedException e){ throw new Error (“Assertion Error”); } // should never happen • What is the point of making a client do this? • Conditions for using checked exceptions: • Exceptional condition cannot be prevented by proper use of the API • Programmer can take some useful action
More Item 59 Standard Transformation: if (obj.actionPermitted(args)) { obj.action(args); } else { // Handle exceptional condition } Or even simply (where appropriate): obj.action(args); // Client allows call to fail
Item 60: Favor Use of Standard Exceptions • IllegalArgumentException - Inappropriate parameter; several special cases • NullPointerException (param null where prohibited) • IndexOutOfBoundsException (index param out of range) • ClassCastException
More Item 60 • IllegalStateException • Object state is inappropriate for method invocation • Object may not be initialized before calling accessing its state • Special subtype: ConcurrentModificationException • Concurrent modification detected where not allowed • UnsupportedOperationException • Object does not support the method • Substitution principal
More Item 60 • Reasons to use standard exceptions: • Using your API is easier • Reading your programs is easier • Performance advantage (relatively minor) • No additional namespace to manage • Note that standard Java exception list is more than the 6 mentioned in Bloch
Item 61: Throw Exceptions Appropriate to the Abstraction • Propagated exceptions may make no sense • Higher layers should translate lower level exceptions // Bad example: public int min (int[] a) { int minVal = a[0]; // Bad: Throws IndexOutOfBoundsException for (int val: a) {if (val < minVal) minVal = val;} return minVal; }
More Item 61: Exception Chaining Transformation: try { // Use low level abstraction to satisfy contract } catch (LowerLevelException cause) { throw new HigherLevelException (cause); } • Achieves 2 very different goals • Gives client exception at expected level of abstraction • Also preserves low level detail for failure analysis
Item 62: Document All Exceptions Thrown by Each Method • Checked Exceptions: • Declare (required by compiler) • And Document (with @throws tag in JavaDoc) • Unchecked Exceptions: • Document (with @throws tag in JavaDoc) • Don’t shortcut with superclass exceptions • Example: Don’t catch “Exception” instead of NullPointerException • Ok to document common exceptions at class level • Example: “All methods in class throw NullPointerException if a null object reference is passed in any parameter”
Item 63: Include Failure-Capture Information in Detail Messages • Uncaught exceptions result in printing of stack trace, including “detail” messages • These messages should contain values of all parameters that “contributed to the exception” • In other words, include relevant state information • Example: IndexOutOfBoundsException includes upper bound, lower bound, and offending index
Item 64: Strive for Failure Atomicity • Failure atomicity: • A failed method invocation should leave the object in the state that it was in prior to the invocation • Ways to achieve this effect: • Design immutable objects • Check parameters for validity before performing the operation • Order the computation – parts that fail come before modification • Write recovery code – cause the object to roll back its state • Perform the operation on a temporary copy of the object
More Item 64: public int addMax(List<Integer> list, Integer x) throws … //pre: true //post: if x is not max w.r.t. list, throw IAE // else append x to list • Don’t throw exception in between modifications to state variables • Procedure should have an atomic effect • throw exception in the beginning if you are not sure you can pull it off
More Item 64 public Object pop() throws … { //Requires: this != EmptyStack //Modifies: this //Effects: pops this and returns top Object result = elements[--size]; elements[size] = null; return result; } // Note: Client can corrupt state – oops!
More Item 64 public Object pop() throws … { //Requires: //Modifies: this //Effects: If this empty throw ISE // else pop this and returns top if (size == 0) { throw new ISE(…); Object result = elements[--size]; elements[size] = null; return result; } // Note atomic execution, normal or exception
Item 65: Don’t Ignore Exceptions • Programmers should never leave a catch block empty • Its easy to ignore exceptions, but don’t! try{ ... }catch(Exception e){ } // empty catch block wont raise complaints // from compiler! Don’t do this!
More Item 65 • If its empty, its highly suspect • The purpose of exception is to force programmers handle exceptional conditions • At least have a comment which explains why its ok to ignore this exception