exceptions and errors in java
TRANSCRIPT
Agenda• Examples• Class Hierarchy• try-catch-finally blocks• multi-catch and try-with-resources• Exception propagation• Checked vs unchecked exceptions• Custom exceptions
Example 1What will be the outcome of the following program and why?
int[] a = {1,2,3,4,5};for (int i = 1; i <= 5 ; i++) { System.out.println(a[i]);}
System.out.println(“Finished”);
Example 1What will be the outcome of the following program and why?
int[] a = {1,2,3,4,5};for (int i = 1; i <= 5 ; i++) { System.out.println(a[i]);}
System.out.println(“Finished”);
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
Example 2What will be the outcome of the following program and why?
static String s;public static void main(String[] args) { System.out.println(s.length());}
Example 2What will be the outcome of the following program and why?
static String s;public static void main(String[] args) { System.out.println(s.length());}
Exception in thread "main" java.lang.NullPointerException
Example 3What will be the outcome of the following program and why?
Integer i = 2;Long l = (Long)(Number) i;System.out.println(l);
Example 3What will be the outcome of the following program and why?
Integer i = 2;Long l = (Long)(Number) i;System.out.println(l);
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
Example 4Fibonacci Numbers
Fib0 = 1Fib1 = 1Fibn = Fibn-1 + Fibn-2
long fib(long i) { if (i == 0) { return 1; } if (i == 1) { return 1; } else { return fib(i - 1) + fib(i - 2); }}
fib(3) = ?fib(100_000) = ?
Example 4Fibonacci Numbers
Fib0 = 1Fib1 = 1Fibn = Fibn-1 + Fibn-2
long fib(long i) { if (i == 0) { return 1; } if (i == 1) { return 1; } else { return fib(i - 1) + fib(i - 2); }}
fib(3) – returns correct answerfib(100_000) - StackOverflowError
Class Hierarchy
serious problems that a reasonable application should not try to catch
Checked exceptions
Unchecked exceptions
conditions that a reasonable application might want to catch
Exceptions in Java 8
Runtime Exceptions is Java 8
Errors in Java 8
Exceptions• Exceptions are thrown by a program, and may be caught and handled by
another part of the program
• A program can have a normal execution flow and an exception execution flow
• Java has a predefined set of exceptions and errors that can occur during execution
• A program can deal with an exception by:• ignoring it (see first examples)• handling it where it occurs• handling it in another place in the program
try-catchtry {//guarded region, i.e. code that might throw exceptions…} catch (Exception1 e1) {//Exception1 handler…} catch (Exception2 e2) {//Exception2 handler…}
- If an exception occurs in try block, the control will get transferred to the appropriate catch handler
- A catch handler shows that we know how to handle exceptions of that type
- If Exception1 is a subclass of Exception2, its catch block should come first (start with the most specific exception)
Exception swallowingDo NOT write catch handlers like this:catch(Exception e) {}- program continues processing as if nothing had gone wrong - the ignored exception may lead the application to an unexpected failure- code can be hard to debug- if the exception really needs to be caught, log some information about it!
ExampleFile file = new File("file.txt");Writer writer = null;try { writer = new PrintWriter(file); writer.write(new BigDecimal("Hello world!").toString()); writer.flush(); writer.close();} catch(FileNotFoundException e) { System.out.println("Caught " + e.getClass().getName());} catch (IOException e) { System.out.println("Caught IOException: " + e.getMessage());} catch (NumberFormatException e) { System.out.println("Caught " + e.getClass().getName());}
What is wrong with the above code?
ExampleFile file = new File("file.txt");Writer writer = null;try { writer = new PrintWriter(file); writer.write(new BigDecimal("Hello world!").toString()); writer.flush(); writer.close();} catch(FileNotFoundException e) { System.out.println("Caught " + e.getClass().getName());} catch (IOException e) { System.out.println("Caught IOException: " + e.getMessage());} catch (NumberFormatException e) { System.out.println("Caught " + e.getClass().getName());}
Is the file always closed?
FixFile file = new File("file.txt");Writer writer = null;try { writer = new PrintWriter(file); writer.write(new BigDecimal("Hello world!").toString()); writer.flush();}catch (NumberFormatException e) { System.out.println("Caught " + e.getClass().getName());}catch(FileNotFoundException e) { System.out.println("Caught " + e.getClass().getName());}catch (IOException e) { System.out.println("Caught IOException "+ e.getMessage());} finally { if (writer != null) try { writer.close(); } catch (IOException e) { System.err.println("Caught IOException"); }}
Finally block• any try block needs to be followed by at least a catch or finally block• finally block always gets executed (unless JVM exits while the try/catch is
being executed or the thread executing the try/catch is interrupted or killed)• if there is a return statement in the try block, the finally block executes right
after the return statement is encountered, and before the return executes• if an exception is thrown, finally block executes immediately after the
corresponding catch block completes• if there is no exception, finally executes immediately after the try block• finally is the ideal place to release resources
Multi-catchFile file = new File("file.txt");Writer writer = null;try { writer = new PrintWriter(file); writer.write(new BigDecimal("Hello world!").toString()); writer.flush();}catch (NumberFormatException | IOException e) { //e is final//the exceptions must be in different inheritance hierarchies System.out.println("Caught " + e.getClass().getName());} finally { if (writer != null) try { writer.close(); } catch (IOException e) { System.out.println("Caught IOException: " + e.getMessage()); }}
try-with-resourcespublic static void main(String[] args) throws IOException {File file = new File("file.txt");try(Writer writer = new PrintWriter(file)) { writer.write(new BigDecimal("Hello world!").toString()); writer.flush();}}
- Code is more concise and readable- Automatic Resource Management closes the file for us- The resources are declared in try between () and must implement
AutoCloseable
throw/throws• A method can throw a new exception: throw new Exception();throw new IllegalArgumentException();
• A method can specify in its declaration that it throws one or more exceptionsvoid f() throws Exception1, Exception2; void f() throws Exception1, Exception2{//…}
Exception propagationpublic static void main(String[] args) { doStuff();}private static void doStuff() { doMoreStuff();}private static void doMoreStuff() { int x = 5/0;}
Exception in thread "main" java.lang.ArithmeticException: / by zeroat Exercise.doMoreStuff(Exercise.java:10)at Exercise.doStuff(Exercise.java:7)at Exercise.main(Exercise.java:4)
Checked vs unchecked exceptionsChecked Exceptions Unchecked Exceptions
Checked by the compiler Unchecked by the compiler
Extend Exception Extend RuntimeException
If a method throws them, they need to be specified in that method’s declaration
If a method throws them, they can be specified in the declaration, but it’s not mandatory
They need to either be caught or rethrown explicitly by a method
No restrictions
Show recoverable conditions Show programming errors
Custom Exceptions• We can create our own business exceptions by extending either
Exception or RuntimeException• We can use our exceptions just like the standard ones
Example - PersonValidatorpublic class Person { private String name; private int age;
public Person() {}
public Person(String name, int age) { this.name = name; this.age = age; } //getters and setters}
public class PersonValidationException extends RuntimeException { public PersonValidationException(String s) { super(s); }}
}
Example - PersonValidatorpublic final class PersonValidator { public static final int MAX_LENGTH = 60; private PersonValidator(){}
public static void validate(Person p) { if (p.getName() == null || p.getName().isEmpty()) { throw new PersonValidationException("The person must have a name"); } if (p.getName().length() > MAX_LENGTH) { throw new PersonValidationException("The name cannot be longer than " + MAX_LENGTH + " characters"); } if (p.getAge() < 18) { throw new PersonValidationException("The person cannot be underage"); } }}
Example - PersonValidatorpublic static void main(String[] args) { Person validPerson = new Person("John", 25); PersonValidator.validate(validPerson);
Person personWithInvalidAge = new Person("Tom", 17); PersonValidator.validate(personWithInvalidAge);}
Benefits of exception handling• detect errors easily without writing additional code to test return
values• exception-handling code is clearly separated from exception-
generating code• the same exception-handling code can deal with several possible
exceptions• code to handle an exception that may occur in the governed region
needs to be written only once
Conclusions• Do NOT swallow exceptions• Use checked exceptions for conditions from which the caller can
reasonably be expected to recover the exceptional condition cannot be prevented by proper use of the API the programmer using the API can take some useful action once confronted
with the exception
• Use runtime exceptions to indicate programming errors (mostly precondition violations)
• By convention: errors are reserved for use by the JVM to indicate resource deficiencies, invariant failures etc. – do NOT subclass Error