Advanced Programming
SUT • Spring 2019
Error handling mechanisms
Exception handling framework
Benefits of exception handling framework
Exception handling in Java
public class Main {
public static Integer getYear(String day) {
String yearString = day.substring(0, 4);
int year = Integer.parseInt(yearString);
return year;
}
public static void main(String[] args) {
String day = "2010/11/29";
Integer year = getYear(day);
System.out.println(year);
}
}
What is wrong with it?
What if day parameter is not a day representation?
day = “salam!”
What if day parameter is malformed?
Day = “29 Nov 2010”
What if day parameter is empty?
String s = "";
What if day parameter is null?
These occasions are called Exception
What to do with exceptions?
Exit the program
Printing the error on console
Returning a special value
e.g. -1
Sometimes the method can’t handle the exception effectively
What should a method do when an exception occurs?
Exit the program?
Suppose you are in a desktop application
Excel, Word, a game, …
Print on console?
edu site
A game
We can return a special value to report an exception
E.g.
return null;
return -1;
return 0;
return “”;
Why not?
There is no special value
There are many exceptions
Ambiguity
Need for documentation
Combination of program code and exception code
public class Main {
public static int minimum(int[] nums) {
int m = Integer.MAX_VALUE;
for (int i : nums) {
m = Math.min(m, i);
}
return m;
}
}
int[] array = {1,2,-1};
int minimumFound = minimum(array);
Exception Handling is a framework for handling exceptions
;-)
It simplifies code
Separates business code and exception code
Exceptional event
Error that occurs during runtime
Cause normal program flow to be disrupted
Examples
Divide by zero errors
Accessing the elements of an array beyond its range
Invalid input
Hard disk crash
Opening a non-existent file
Heap memory exhausted
Provided by Java runtime
Prints out exception description
Prints the stack trace
Hierarchy of methods where the exception occurred
Causes the program to terminate
class DivByZero {
public static void main(String a[]) {
System.out.println(3/0);
}
}
Exception in thread "main" java.lang.ArithmeticException:
/ by zero
at exception.Test2.main(Test2.java:19)
When an exception occurs within a method
The method creates an exception object
And hands it off to the runtime system
This job is called “throwing an exception”
Exception object contains
information about the error
its type
the state of the program when the error occurred
Exception line of code
The run time system searches the call stack for a method that contains an exception handler
When an appropriate handler is found
The runtime system passes the exception to the handler
The exception handler catches the exception
What if the runtime system can not find an exception handler?
Uses the default exception handler
import java.util.Scanner;
public class Year {
public static Integer getYear(String day) {
String yearString = day.substring(0, 4);
return Integer.parseInt(yearString);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter a well-formed date: ");
String date = scanner.next();
Integer year = getYear(date);
System.out.println(year);
}
}
public class Year {
public static Integer getYearWithException(String day) throws Exception {
if (day == null)
throw new Exception("null value");
if (day.length() == 0)
throw new Exception("empty value");
if (!matchesDateFormat(day))
throw new Exception("malformed value");
String yearString = day.substring(0, 4);
int year = Integer.parseInt(yearString);
return year;
}
private static boolean matchesDateFormat(String input) {
return input.matches("\\d\\d\\d\\d/\\d\\d/\\d\\d");
}
}
public class Year {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
boolean ok = false;
while (ok == false) {
System.out.print("Enter a well-formed date: ");
String date = scanner.next();
try {
Integer year = getYear(date);
System.out.println(year);
ok = true;
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
throw
throws a new exception
throws
Declares exception throw
If a method may throw an exception, it should declare it
try
Start a block with exception handling
catch
Catch the exception
Separating Error-Handling code from “regular” business logic code
Propagating errors up the call stack
Grouping and differentiating error types
public class Test {
public static void main(String[] args){
try {
Scanner scanner = new Scanner(System.in);
int first = scanner.nextInt();
int second = scanner.nextInt();
int div = division(first, second);
System.out.println(div);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
private static int division(int first, int second) throws Exception{
if(second == 0)
throw new Exception("OOPS! Makhraj Sefre!");
return first/second;
}
}
Consider pseudocode method
It reads an entire file into memory
readFile {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
}
errorCodeType readFile {
initialize errorCode = 0;
open the file;
if(theFileIsOpen) {
determine the length of the file;
if(gotTheFileLength) {
allocate that much memory;
if(gotEnoughMemory) {
read file int memory;
if(readFailed) {
errorCode = -1;
}
} else {
errorCode = -2;
}
} else {
errorCode = -3;
}
close the file;
if (theFileDidntClose && errorCode == 0) {
errorCode = -4;
} else {
errorCode = errorCode and -4;
}
} else {
errorCode = -5;
}
return errorCode;
}
readFile {
try {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
} catch (fileOpenFailed) {
doSomething;
} catch (sizeDeterminationFailed) {
doSomething;
} catch (MemoryAllacationFailed) {
doSomething;
} catch (readFailed) {
doSomething;
} catch (fileCloseFailed) {
doSomething;
}
}
You should still write code for detecting, reporting and handling exceptions
Exception handling framework is not responsible for these jobs!
It only helps you organize the work more effectively
Traditional approach
Each method should explicitly forward the exception
Use a special return code
Using return type for reporting exceptions
Smells bad!
New approach
Automatic
Beautiful!
All exceptions thrown within a program are objects
The grouping or categorizing of exceptions is a natural outcome of the class hierarchy
public class Test {
public static void main(String[] args){
try {
Scanner scanner = new Scanner(System.in);
int first = scanner.nextInt();
int second = scanner.nextInt();
int div = division(first, second);
System.out.println(div);
} catch (IOException e) {
System.out.println(e.getMessage());
} catch (ArithmeticException e) {
System.out.println(e.getMessage());
}
}
private static int readInt() throws IOException {
String str = scanner.next();
if(str.matches("[\\d]+")){
return Integer.parseInt(str);
}
throw new IOException("Bad input");
}
private static int division(int first, int second) throws ArithmeticException{
if(second == 0)
throw new ArithmeticException("OOPS! Makhraj Sefre!");
return first/second;
}
}
public class MultipleCatch {
public static void main(String args[]) {
try {
int den = Integer.parseInt(args[0]);
System.out.println(3 / den);
} catch (ArithmeticException exc) {
System.out.println("Divisor was 0.");
} catch (ArrayIndexOutOfBoundsException exc2) {
System.out.println("Missing argument.");
}
System.out.println("After exception.");
}
}
public class NestedTryDemo {
public static void main(String args[]) {
try {
int a = Integer.parseInt(args[0]);
try {
int b = Integer.parseInt(args[1]);
System.out.println(a / b);
} catch (ArithmeticException e) {
System.out.println("Div by zero error !");
}
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Need 2parameters !");
}
}
}
Don’t Use Exception instead of If-else
Use exceptions for exceptions!
Your class should extend Exception class
Exception subclasses could be thrown and caught
Steps to follow
Create a class that extends Exception class
Customize the class
Members and constructors may be added to the class
Exception classes are usually simple classes
With no (or few) methods and properties
public class HateStringExp extends Exception {
/* some code */
public static void main(String[] args) {
String input = "invalid input";
try {
if (input.equals("invalid input")) {
throw new HateStringExp();
}
System.out.println("Accept string.");
} catch (HateStringExp e) {
System.out.println("Hate string!");
}
}
}
public class Year {
public static Integer getYear(String day)
throws Exception {
if (day == null)
throw new NullPointerException();
if (day.length() == 0)
throw new EmptyValueException();
if (!matchesDateFormat(day))
throw new MalformedValueException();
String yearString = day.substring(0, 4);
int year = Integer.parseInt(yearString);
return year;
}
private static boolean matchesDateFormat(String input) {
return input.matches("\\d\\d\\d\\d/\\d\\d/\\d\\d");
}
}
try {
//..
} catch (ExceptionType e) {
//…
} ...
} finally {
<code to be executed before the try block ends>
}
Contains the code for cleaning up after a try or a catch
Block of code is always executed
Despite of different scenarios:
Normal completion
Forced exit occurs using a return, a continue or a break statement
Caught exception thrown
Exception was thrown and caught in the method
Uncaught exception thrown
Exception thrown was not specified in any catch block in the method
public class Main {
static void myMethod(int n) throws Exception {
try {
switch(n) {
case 1:
System.out.println("1 case");
return;
case 3:
System.out.println("3 case");
throw new RuntimeException("3!");
case 4:
System.out.println("4 case");
throw new Exception("4!");
case 2:
System.out.println("2nd case");
// continued ...
}
} catch (RuntimeException e) {
System.out.println("RuntimeException: ");
System.out.println(e.getMessage());
} finally {
System.out.println("try-block entered.");
}
}
}
class MyException extends Exception {}
public class Main {
public static int myMethod(int n) {
try {
switch (n) {
case 1:
System.out.println("One");
return 1;
case 2:
System.out.println("Two");
throw new MyException();
case 3:
System.out.println("Three");
}
return 4;
} catch (Exception e) {
System.out.println("catch");
return 5;
} finally {
System.out.println("finally");
return 6;
}
}
int a = myMethod(1);
System.out.println("myMethod(1)=" + a);
a = myMethod(2);
System.out.println("myMethod(2)=" + a);
a = myMethod(3);
System.out.println("myMethod(3)=" + a);
private static void function(String[] args) {
int den = Integer.parseInt(args[0]);
System.out.println(3 / den);
}
public static void main(String[] args) {
function(args);
}
The method function() may throw exceptions
But it has not declared it with throws keyword
Why?
Because some exceptions are unchecked
such as ArithmeticException and ArrayIndexOutOfBoundsException
Checked exception
Java compiler checks
the program should catch or list the occurring exception
If not, compiler error will occur
Unchecked exceptions
Not subject to compile-time checking for exception handling
Built-in unchecked exception classes
Error
RuntimeException
Their subclasses
Unchecked exceptions only relax compiler
The runtime behavior is the same
Multiple catches should be ordered from subclass to superclass
Or else, Compile error: Unreachable catch block…
class MultipleCatchError {
public static void main(String args[]){
try {
int a = Integer.parseInt(args [0]);
int b = Integer.parseInt(args [1]);
System.out.println(a/b);
} catch (ArrayIndexOutOfBoundsException e) {
//..
} catch (Exception ex) {
//..
}
}
}
Suppose method f() overrides parent’s method
f() in child class can not throw more exceptions than those of f() in Parent class
Less or equal exceptions in throws declaration
These mistakes bring compiler error
Why?
Polymorphic method invocations may cause failure in catching some exceptions
class Parent{
void f() {}
}
class Child extends Parent{
void f() throws Exception {}
}
Result?
Compiler Error
class Parent{
void f() throws ArithmeticException {}
}
class Child extends Parent{
void f() throws ArithmeticException, IOException {}
}
Result?
Compiler Error
class Parent{
void f() throws ArithmeticException {}
}
class Child extends Parent{
void f() throws Exception {}
}
Result?
Compiler Error
class Parent{
void f() throws Exception{}
}
class Child extends Parent{
void f() throws ArithmeticException{}
}
Result?
No Error
f() in child class can not throw more exceptions
Less or equal exceptions in throws declaration
f() in child class can not throw more general exceptions
f() in child class can throw more specific exceptions
Reason:
Prevent uncaught exceptions in polymorphic invocations
class MyException extends Exception {
public MyException(String string) {
super(string);
}
}
class YourException extends RuntimeException {
public YourException(String string) {
super(string);
}
}
public class Sample {
public static void main(String[] args) {
try {
f();
System.out.println("After f()");
throw new YourException("Your Exception");
} catch (MyException e) {
System.out.println("My Exception");
} catch (Exception e) {
System.out.println("Exception");
} finally {
System.out.println("Finally");
}
}
private static void f() throws Exception {
System.out.println("f() method");
throw new MyException("Exception");
}
}
interface A {
void a(Object o);
}
interface B {
void b(String s);
}
class C implements A {
public void a(Object o) {
System.out.println("a() in C");
}
public void b(String s) {
System.out.println("b() in C");
}
}
class D extends C implements A, B {
public void a(Object o) {
System.out.println("a() in D");
super.a(o);
}
public void b(String s) {
System.out.println("b() in D");
try {
int parseInt = Integer.parseInt(s);
} catch (Exception e) {
//NumberFormatException
throw new BadFormatException();
}
}
}
class BadFormatException extends
RuntimeException {
}
public class Test {
public static void main(String[] args) {
A a1 = new C();
B b1 = new D();
C c1 = new C();
C c2 = new D();
Object o = new String("Twenty Two");
try {
f(c2);
a1.a(o);
c1.a((String) o);
b1.b((String) o);
c2.a(o);
} catch (NumberFormatException e) {
System.out.println("NumberFormatException");
} catch (BadFormatException e) {
System.out.println("BadFormatException");
} catch (Exception e) {
System.out.println("Exception");
} finally {
System.out.println("Good Bye!");
}
}
public static void f(A a) {
a.a(a);
}
}
e.printStackTrace();
e.getStackTrace();
for(StackTraceElement methodCall : e.getStackTrace())
System.out.println(methodCall);
When providing multiple catch handlers:
handle specific exceptions before handling general exceptions.
Multi-Catch Blocks (Java7):
catch(IOException | IllegalStateException multie) {…}
try(Scanner sc = new Scanner(System.in)) {
System.out.println("You Typed the integer value: " + sc.nextInt());
} catch (Exception e){
// catch all other exceptions here ...
System.out.println("Error: Encountered an exception and could not read
an integer from the console ...");
System.out.println("Exciting the program -
restart and try the program again!");
}
java.lang.AutoCloseable interface
The assert statement
used to check your assumptions about the programs
E.g.
assert (i >= 0) : "impossible: i is negative!";
AssertionError
java -ea MyClassName
The key to understanding assertions
they are useful for debugging and testing
Assertions are meant to be disabled when the application is deployed to end users