1 of 35

Lecture 5

Exceptions

Some slides were borrowed from Josh Hug and Adam Jundt

2 of 35

Reminders

  1. Mic
  2. PA01 feedback (part of the grade), on Canvas
    1. For each PA
    2. After the submission period is over.

3 of 35

Exceptions

4 of 35

Exceptions

  • An exception is abnormal condition in which the normal execution of a code gets interrupted.

  • Open a file
  • Divide by zero
  • Access invalid cell in array
  • ...

5 of 35

Exceptions

  • 2 types
    • Checked exceptions: you have to catch those, otherwise the program will not compile: (java.lang.Exceptions)
      • ClassNotFound
      • IOExceptions

6 of 35

Exceptions

  • 2 types
    • Checked exceptions: you have to catch those, otherwise the program will not compile.
    • Runtime (unchecked) exceptions: problems during runtime: java.lang.RunTimeException
      • ArithmeticException
      • IndexOutOfBounds
      • IllegalArgumentException
      • ...

7 of 35

Handling Errors

Sometimes things go wrong, e.g.

  • You try to use 383,124 gigabytes of memory.
  • You try to call a method using a reference variable that is equal to null.
  • You try to access index -1 of an array.

The Java approach to handling these exceptional events is to throw an exception.

  • Disrupts normal flow of the program.
  • You saw that these exceptions just cause the program to crash, printing out a helpful (?) message for the user.

8 of 35

Exceptions: May be Explicitly or Implicitly Thrown

Java itself can throw exceptions implicitly, e.g.

String t = "Marina";

int n = Integer.parseInt(t);

9 of 35

Exceptions: May be Explicitly or Implicitly Thrown

Java itself can throw exceptions implicitly, e.g.

Java code can also throw exceptions explicitly using throw keyword:

public static void main(String[] args) {

System.out.println("ayyy lmao");

throw new RuntimeException("For no reason.");

}

Creates new object of type RuntimeException!

$ java Alien

ayyy lmao

Exception in thread "main" java.lang.RuntimeException: For no reason.

at Alien.main(Alien.java:4)

String t = "Marina";

int n = Integer.parseInt(t);

10 of 35

Problem

class Exceptions {

static int num = 10;

public static void main(..) {

double result = divideByNumber(0);

}

public static double divideByNumber (int d) {

return num/d;

}

}

11 of 35

try... catch

12 of 35

Solution

class Exceptions {

static int num = 10;

public static void main(..) {

double result = divideByNumber(0);

}

public static double divideByNumber (int d) {

return num/d;

}

}

13 of 35

Solution

class Exceptions {

static int num = 10;

public static void main(..) {

double result = divideByNumber(0);

}

public static double divideByNumber (int d) {

return num/d;

}

}

14 of 35

try... catch again

try {

// code

}

catch(IndexOutOfBounds e) {

// code

}

catch(ArithmeticExpection e) {

// code

}

15 of 35

try_catch and Declaring

exceptions

16 of 35

DEclaring an exception. User’s problem (demo)

  • Methods can cause an exception, and instead of fixing it, just report to whoever called it

17 of 35

Method pop from Java doc

18 of 35

There are two ways to handle exceptions:

  1. Use try/catch block
  2. Use throws clause

19 of 35

Throw and checked exceptions, demo

20 of 35

Throw: Explicitly throw an exception

A: IllegalArgumentException: Too Young

B: IllegalArgumentException: Too Young

Welcome to my party!

C:

IllegalArgumentException: Too Young

Welcome to my party!

IllegalArgumentException: Too Old

D: Something else

21 of 35

Checked Exception

(code will not compile)

Slides were borrowed from Josh Hug

22 of 35

“Must be Caught or Declared to be Thrown”

Occasionally, you’ll find that your code won’t even compile, for the mysterious reason that an exception “must be caught or declared to be thrown”.

  • The basic idea: Some exceptions are considered so disgusting by the compiler that you MUST handle them somehow.
  • We call these “checked” exceptions.

public static void main(String[] args) {

Eagle.gulgate();

}

$ javac What.java

What.java:2: error: unreported exception IOException; must be caught or declared to be thrown

Eagle.gulgate();

^

23 of 35

Checked Exceptions

Examples so far have been unchecked exceptions. There are also checked exceptions:

  • Compiler requires that these be “caught” or “specified”.
    • Goal: Disallow compilation to prevent avoidable program crashes.
  • Example:

public class Eagle {

public static void gulgate() {

if (today == “Wed”) {

throw new IOException("hi"); }

}

}

To be defined soon...

$ javac Eagle

Eagle.java:4: error: unreported exception IOException; must be caught or declared to be thrown

throw new IOException("hi"); }

^

24 of 35

Unchecked Exceptions

By contrast unchecked exceptions have no such restrictions.

  • Code below will compile just fine (but will crash at runtime).

public class UncheckedExceptionDemo {

public static void main(String[] args) {

if (today == “Wed”) {

throw new RuntimeException("as a joke"); }

}

}

$ javac UncheckedExceptionDemo.java

$ java UncheckedExceptionDemo

Exception in thread "main" java.lang.RuntimeException: as a joke.

at UncheckedExceptionDemo.main(UncheckedExceptionDemo.java:3)

25 of 35

Checked vs. Unchecked Exceptions

Any subclass of RuntimeException or Error is unchecked, all other Throwables are checked.

Throwable

Error

Exception

Runtime

Exception

IOException

Midi

Unavailable

Exception

FileNotFound

Exception

IndexOutOf

BoundsException

Assertion

Error

...

unchecked

checked

26 of 35

Checked vs. Unchecked

  • Compiles fine, because the possibility of unchecked exceptions is allowed:

  • Won’t compile, because there exists possibility of checked exception.

public class UncheckedExceptionDemo {

public static void main(String[] args) {

if (today == “Wed”) {

throw new RuntimeException("as a joke"); }

}

}

public class Eagle {

public static void gulgate() {

if (today == “Wed”) {

throw new IOException("hi"); }

}

}

Java considers this an “unchecked” exception.

Java considers this a “checked” exception.

Why didn’t you catch or specify??

27 of 35

Checking Exceptions

Compiler requires that all checked exceptions be caught or specified.

Two ways to satisfy compiler:

  • Catch: Use a catch block after potential exception.

  • Specify method as dangerous with throws keyword.

public static void gulgate() {

try {

if (today == “Wed”) {

throw new IOException("hi"); }

} catch (Exception e) { #is ok

System.out.println("psych!");

}

}

28 of 35

Checking Exceptions

Compiler requires that all checked exceptions be caught or specified.

Two ways to satisfy compiler:

  • Catch: Use a catch block after potential exception.
  • Specify method as dangerous with throws keyword.
    • Defers to someone else to handle exception.

public static void gulgate() throws IOException {

... throw new IOException("hi"); ...

}

29 of 35

Checking Exceptions

If a method uses a ‘dangerous’ method (i.e. might throw a checked exception), it becomes dangerous itself.

$ javac What.java

What.java:2: error: unreported exception IOException; must be caught or declared to be thrown

Eagle.gulgate();

^

How do we fix this?

Catch or specify!

public static void gulgate() throws IOException {

... throw new IOException("hi"); ...

}

public static void main(String[] args) {

Eagle.gulgate();

}

30 of 35

Checking Exceptions

Two ways to satisfy compiler: Catch or specify exception.

Specify that you might throw an exception.

Use when someone else should handle.

public static void gulgate() throws IOException {

... throw new IOException("hi"); ...

}

public static void main(String[] args) {

try {

Eagle.gulgate();

} catch(IOException e) {

System.out.println("Averted!");

}

}

Catch an Exception:

Keeps it from getting out.

Use when you can handle the problem.

public static void main(String[] args)

throws IOException {

Eagle.gulgate();

}

31 of 35

Throws vs throw

public int pop() throws EmptyStackException {� int obj;�� if (size == 0) {� throw new EmptyStackException();� }�� obj = objectAt(size - 1);� setObjectAt(size - 1, null);� size--;� return obj;�}

32 of 35

Not checked, so

public int pop() throws EmptyStackException {� int obj;�� if (size == 0) {� throw new EmptyStackException();� }�� obj = objectAt(size - 1);� setObjectAt(size - 1, null);� size--;� return obj;�}

https://beginnersbook.com/2013/04/difference-between-throw-and-throws-in-java/

33 of 35

Why Exceptions?

Allows you to keep error handling code separate from ‘real’ code.

  • Consider pseudocode that reads a file:

func readFile: {

open the file;

determine its size;

allocate that much memory;

read the file into memory;

close the file;

}

what if the file doesn’t exist?

what if there’s not enough memory?

what happens if reading fails?

34 of 35

Error Handling Code (Naive)

One naive approach to the right.

  • Clearly a bad idea.

func readFile: {

open the file;

determine its size;

allocate that much memory;

read the file into memory;

close the file;

}

func readFile: {

open the file;

if (theFileIsOpen) {

determine its size;

if (gotTheFileLength) {

allocate that much memory;

} else {

return error("fileLengthError");

}

if (gotEnoughMemory) {

read the file into memory;

if (readFailed) {

return error("readError");

}

...

} else {

return error("memoryError");

}

} else {

return error("fileOpenError")

}

}

35 of 35

With Exceptions

func 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 (memoryAllocationFailed) {

doSomething;

} catch (readFailed) {

doSomething;

} catch (fileCloseFailed) {

doSomething;

}

}

func readFile: {

open the file;

if (theFileIsOpen) {

determine its size;

if (gotTheFileLength) {

allocate that much memory;

} else {

return error("fileLengthError");

}

if (gotEnoughMemory) {

read the file into memory;

if (readFailed) {

return error("readError");

}

...

} else {

return error("memoryError");

}

} else {

return error("fileOpenError")

}

}