Exceptions SWE 619: Software Construction Last Modified Spring 2010 Saket Kaushik, Paul Ammann Inputs to Procedures Sqrt procedure public float sqrt (float x) Square root can only be calculated for non negative floats. sqrt() does not makes sense for negative floating point numbers. Procedure definition allows any float value to be passed (positive or negative) How should a procedure cope with negative floats? Use Partial Procedures? Usually a bad idea 2 Partial Procedures Announces its contract for use Set of preconditions that must be ensured at the time of invocation Theoretically sound… Guarantees post conditions subject to preconditions BUT clients can always call method without satisfying preconditions How does code behave in such a case Not possible to be sure what client gets back What happens in next release? Do clients rely on undocumented behavior? 3 Handling Undefined Inputs “Normal” processing is not possible Only option: Define behavior to inform client How to inform client? One option: Return special values float sqrt (float x) //Effects: if x>=0.0 returns approx square root; // if x <0.0 returns 0.0 4 Problems with special values float sqrt (float x) //Effects: if x>=0.0 returns approx square root; // if x <0.0 returns 0.0 Consider following calls: float root1 = sqrt(-45.4); float root2 = sqrt(0.0); if(root1-root2) {bla bla…} if special value is a possible return value of the procedure, it results in ambiguities no leftover values to use 5 Problems with special values public int search(int [ ] a, int x) //Effects: If a not null and not empty, //returns index of x in a if present; else //returns -1 not found? empty? null? 6 Alternate approach: Exceptions Provide an alternate return mechanism No overlap with ‘real’ values ArrayIndexOutofBoundsException never overlaps with another real value, but -1 or null does Exceptions force client to treat special values ‘specially’ usually in a separate code block; not in the normal execution sequence. 7 Specifications Signature: public int foobar(int x, int y) throws <List of exceptions> e.g: float sqrt (float x) throws NegativeNumberException Liskov: List all Exceptions thrown Bloch: List only checked exceptions We will generally follow Liskov, but the issue is mostly about style, not substance 8 Requires Effects Effects clause should explain what causes each exception to be thrown, define behavior for all inputs in require clause float sqrt (float x) //Requires: x>=0.0 //Effects: … float sqrt (float x) //Requires: //Effects: If x < 0.0 throw //NegativeNumberException; … float sqrt (float x) throws NNE //Effects: If x< 0.0 throw NNE; … 9 Java Exception Mechanism Throwable Error RuntimeException Exception … Checked Exceptions … Unchecked Exceptions 10 Exceptions Unchecked: client does not need to explicitly write special code Checked: client has to pay attention to these. Must write special code blocks Many different types of exceptions are provided. You can provide your own. 11 Custom Exceptions public MyFavoriteException extends Exception { public MyFavoriteException() { super(); } public MyFavoriteException(String s) {super(s);} can add more like state at the time of throwing the exception methods that let the invalid state be printed and other useful information 12 Throwing Exceptions Explicit throws throw new NullPointerException(“”); throw new NPE(“class, method”); System throws String [ ] a = {“1”,”2”,”3”,”4”,”5”}; print(a[-1]); System throws IndexOOBE Passing through (goes up the call chain) keeps going till it finds a handler 13 Catching Exceptions In a special code block called try-block try{ }catch(ExceptionType instance){ } 14 Catching Exceptions Can have multiple catch blocks, with different execution logic for different exceptions raised Class hierarchy matters in catching If you catch an exception of type Exception, all subtypes are also caught catching Exception is dangerous. WHY? 15 Remember! try-catch block should be as short as possible. catch the right type of exception: to be sure of what’s the right thing to do 16 Reflection Vs. Masking Masking: handle the exception in the procedure. client does not expect the exception client may not understand the exception Reflection: pass it over to the calling code client expects it 17 Reflection Example public static int min (int[] a) throws NPE,EE { // Effects if a is null throw NPE else if a is empty throw EE else return min value in a int m; try { m = a[0];} catch (IOOBE e) { throw new EE (“Arrays.min”); } for (int i=0; i < a.length; i++) if (a[i] < m) m = a[i]; return m;} 18 Masking Example public static boolean sorted (int[] a) throws NPE { // Effects if a is null throw NPE else if a is sorted in ascending order return true else return false int p; try { p = a[0];} catch (IOOBE e) { return true; } for (int i=0; i < a.length; i++) if (p < a[i]) {p = a[i];} else {return false;} return true;} 19 Meyer vs Liskov Meyer’s approach is clean and easy to understand software by contract! if preconditions not met, it’s the client’s fault. Client should suffer! Recognizes 1 exception: Failure exception Industry practice is to follow Liskov 20