Exception
Advanced Programming
SUT • Spring 2019
Contents
-
Error handling mechanisms
-
Exception handling framework
-
Benefits of exception handling framework
-
Exception handling in Java
Exception Handling
Example
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);
}
}
Exceptions
-
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
-
Handling Exceptions
-
What to do with exceptions?
-
-
Exit the program
-
Printing the error on console
-
Returning a special value
-
e.g. -1
-
Important Note
-
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
-
Returning a Special Value
-
We can return a special value to report an exception
-
E.g.
-
return null;
-
return -1;
-
return 0;
-
return “”;
-
-
Why not?
Why not?
-
There is no special value
-
There are many exceptions
-
Ambiguity
-
Need for documentation
-
-
Combination of program code and exception code
There is no special value
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
-
Exception Handling is a framework for handling exceptions
-
;-)
-
-
It simplifies code
-
Separates business code and exception code
-
What is an Exception?
-
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
-
Default Exception Handling
-
Provided by Java runtime
-
Prints out exception description
-
Prints the stack trace
-
Hierarchy of methods where the exception occurred
-
-
Causes the program to terminate
Example
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)
- Note: Exception is a runtime concept
- This code has no syntax error (No compile-time error)
What Happens When an Exception Occurs?
-
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
-
-
What Happens When an Exception Occurs (2)?
-
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
-
Example
Example
Exception Handling in Java
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);
}
}
Example
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");
}
}
main
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());
}
}
}
}
Exception Handling Keywords
-
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
-
Benefits of Exception Handling Framework
-
Separating Error-Handling code from “regular” business logic code
-
Propagating errors up the call stack
-
Grouping and differentiating error types
Example
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;
}
}
Separating Error-Handling Code
-
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;
}
With Exception
Handling Framework
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;
}
}
Note
-
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
Propagating Errors Up the Call Stack
-
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!
-
Grouping and Differentiating Error Types
-
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;
}
}
Example
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.");
}
}
Nested Tries
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 !");
}
}
}
Bad Use of Exceptions
-
Don’t Use Exception instead of If-else
-
Use exceptions for exceptions!
Writing Your Own 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
-
Example
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!");
}
}
}
getYear(), revisited
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");
}
}
Finally
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
Finally (2)
-
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
-
What is the output of:
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.");
}
}
}
What is the output of:
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);
Unchecked Exceptions
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 and Unchecked Exceptions
-
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
-
Checked and Unchecked Exceptions
-
Built-in unchecked exception classes
-
Error
-
RuntimeException
-
Their subclasses
-
-
Unchecked exceptions only relax compiler
-
The runtime behavior is the same
-
Exception Class Hierarchy
Exception Classes and Hierarchy
-
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) {
//..
}
}
}
Exceptions & Inheritance
-
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
-
Example (1)
class Parent{
void f() {}
}
class Child extends Parent{
void f() throws Exception {}
}
-
Result?
-
Compiler Error
-
Example (2)
class Parent{
void f() throws ArithmeticException {}
}
class Child extends Parent{
void f() throws ArithmeticException, IOException {}
}
-
Result?
-
Compiler Error
-
Example (3)
class Parent{
void f() throws ArithmeticException {}
}
class Child extends Parent{
void f() throws Exception {}
}
-
Result?
-
Compiler Error
-
Example (4)
class Parent{
void f() throws Exception{}
}
class Child extends Parent{
void f() throws ArithmeticException{}
}
-
Result?
-
No Error
-
Conclusion
-
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");
}
}
Example
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);
}
}
Accessing the Stack Trace
-
e.printStackTrace();
-
e.getStackTrace();
for(StackTraceElement methodCall : e.getStackTrace())
System.out.println(methodCall);
Multiple Catch Blocks
-
When providing multiple catch handlers:
-
handle specific exceptions before handling general exceptions.
-
Multi-Catch Blocks (Java7):
catch(IOException | IllegalStateException multie) {…}
Try-with-Resources (Java7)
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
Assertions
-
The assert statement
-
used to check your assumptions about the programs
-
E.g.
-
assert (i >= 0) : "impossible: i is negative!";
-
-
AssertionError
-
java -ea MyClassName
Assert or Exception?
-
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
Title Text
Exception
By Behnam Hatami
Exception
Exception / Advanced Programming Course @ SUT, Spring 2019
- 967