Exception Handling

Try-catch-finally, throw/throws, try-with-resources, custom exceptions and exception types.


Exception handling keeps programs running when runtime errors occur; an exception is an object thrown at runtime that disrupts flow. Checked exceptions (IOException, SQLException) must be handled or declared; unchecked ones extend RuntimeException or Error. try holds risky statements, catch handles the exception, finally always runs, throw raises one, throws declares it. try-with-resources closes resources; custom exceptions extend Exception.

Example
try(FileOutputStream fos = new FileOutputStream("abc.txt")) {
  fos.write(msg.getBytes());
}
Code Snippets 10
TryCatchException
Basic

TryCatchException

package vs.exception;
class TryCatchException {
  public static void main(String args[]) {
    int a = 10;
    int b = 5;
    int c = 5;
    try {
      int x = a /(b + c);
      System.out.println("x=" + x);
      int y = a /(b - c);
      // Error division by zero
      System.out.println("y=" + y);
    } catch(ArithmeticException e) {
      //exception is handled
      System.out.println(e);
    }
  }
}

1. Runtime error (ArithmeticException - divide by zero)
Basic

1. Runtime error (ArithmeticException - divide by zero)

package vs.exception;
// ------------------------------------------------------------------
// 1. Runtime error (ArithmeticException - divide by zero)
// ------------------------------------------------------------------
class ErrorExample {
  public static void main(String[] args) {
    int a = 10;
    int b = 5;
    int c = 5;
    int x = a /(b + c);
    // 10 / 10 = 1
    System.out.println("x = " + x);
    int y = a /(b - c);
    // 10 / 0 -> ArithmeticException (crash!)
    System.out.println("y = " + y);
    // this line never runs
  }
}

2. Handling the exception with try-catch
Basic

2. Handling the exception with try-catch

package vs.exception;
// ------------------------------------------------------------------
// 2. Handling the exception with try-catch
// ------------------------------------------------------------------
class TryCatchDemo {
  public static void main(String[] args) {
    int a = 10;
    int b = 5;
    int c = 5;
    try {
      int x = a /(b + c);
      System.out.println("x = " + x);
      int y = a /(b - c);
      // divide by zero
      System.out.println("y = " + y);
    } catch(ArithmeticException e) {
      System.out.println("ArithmeticException caught: " + e);
    }
    System.out.println("Program continues normally...");
  }
}

3. Exception hierarchy overview
Basic

3. Exception hierarchy overview

package vs.exception;
// ------------------------------------------------------------------
// 3. Exception hierarchy overview
//    Throwable
//     |-- Error            (unchecked, irrecoverable e.g. OutOfMemoryError)
//     |-- Exception        (checked)
//         |-- RuntimeException  (unchecked)
//             |-- ArithmeticException, NullPointerException,
//             |-- ArrayIndexOutOfBoundsException, etc.
//         |-- IOException, SQLException  (checked)
// ------------------------------------------------------------------
class ExceptionHierarchy {
  public static void main(String[] args) {
    // unchecked exceptions are NOT checked at compile time
    demonstrateNullPointer();
    demonstrateIndexOutOfBounds();
  }
  static void demonstrateNullPointer() {
    String s = null;
    try {
      System.out.println(s.length());
      // NullPointerException
    } catch(NullPointerException e) {
      System.out.println("NullPointerException: " + e);
    }
  }
  static void demonstrateIndexOutOfBounds() {
    int[] arr = {
      1,2, 3
    }
    ;
    try {
      System.out.println(arr[10]);
      // ArrayIndexOutOfBoundsException
    } catch(ArrayIndexOutOfBoundsException e) {
      System.out.println("IndexOutOfBounds: " + e);
    }
  }
}

4. Checked exceptions - the compiler forces you to handle them
Basic

Checked exceptions - the compiler forces you to handle them

package vs.exception;
// ------------------------------------------------------------------
// 4. Checked exceptions - the compiler forces you to handle them
// ------------------------------------------------------------------
import java.io.*;
class CheckedExceptionDemo {
  public static void main(String[] args) {
    // The compiler requires handling of the checked IOException
    try {
      FileReader fr = new FileReader("nonexistent.txt");
      BufferedReader br = new BufferedReader(fr);
      String line = br.readLine();
      System.out.println(line);
      br.close();
    } catch(IOException e) {
      System.out.println("IOException caught: " + e);
    }
  }
}

5. Three ways to handle - try-catch, throws, try-catch-finally.
Basic

5. Three ways to handle - try-catch, throws, try-catch-finally.

package vs.exception;
// ------------------------------------------------------------------
// 5. Three ways to handle - try-catch, throws, try-catch-finally.
//    Structure of a full handler
// ------------------------------------------------------------------
class FullHandler {
  public static void main(String[] args) {
    int a = 10, b = 0;
    try {
      int result = a / b;
      System.out.println("Result = " + result);
    } catch(ArithmeticException e) {
      System.out.println("Caught: " + e.getMessage());
    } finally {
      System.out.println("finally always executes");
    }
    System.out.println("After try-catch-finally");
  }
}

Types of Exception
Basic

Types of Exception
Topic: Errors, unchecked vs checked exceptions, single try-catch, nested try-catch, multiple catch blocks

// ============================================================
// Session 2 - Types of Exception
// Topic: Errors, unchecked vs checked exceptions, single try-catch,
//        nested try-catch, multiple catch blocks
// ============================================================
// ------------------------------------------------------------------
// 1. Errors - irrecoverable (OutOfMemoryError etc.)
// ------------------------------------------------------------------
class ErrorsDemo {
  public static void main(String[] args) {
    // An Error is NOT meant to be caught/handled normally.
    // Example: recursive call without termination -> StackOverflowError
    try {
      recurse(1);
    } catch(StackOverflowError e) {
      System.out.println("StackOverflowError occurred: " + e);
    }
    System.out.println("Note: errors usually mean the program state is broken");
  }
  static void recurse(int n) {
    System.out.println(n);
    recurse(n + 1);
    // no base case -> StackOverflowError
  }
}
// ------------------------------------------------------------------
// 2. Single try-catch block (from PPT)
// ------------------------------------------------------------------
class SingleTryCatch {
  public static void main(String[] args) {
    int a = 10;
    int b = 5;
    int c = 5;
    try {
      int x = a /(b + c);
      System.out.println("x = " + x);
      int y = a /(b - c);
      // ArithmeticException
      System.out.println("y = " + y);
    } catch(ArithmeticException e) {
      System.out.println(e);
      // prints exception info
    }
  }
}
// ------------------------------------------------------------------
// 3. Nested try-catch blocks (from PPT)
// ------------------------------------------------------------------
class NestedTryBlock {
  public static void main(String[] args) {
    try {
      try {
        int b = 39 / 0;
        // ArithmeticException
        System.out.println(b);
      } catch(ArithmeticException e) {
        System.out.println(e);
      }
      try {
        int a[] = new int[10];
        a[10] = 50;
        // ArrayIndexOutOfBoundsException
      } catch(ArrayIndexOutOfBoundsException e) {
        System.out.println(e);
      }
      System.out.println("other statement");
    } catch(Exception e) {
      // catches anything else
      System.out.println("handled the exception (outer catch)");
    }
    System.out.println("normal flow..");
  }
}
// ------------------------------------------------------------------
// 4. Multiple catch blocks
// ------------------------------------------------------------------
class MultipleCatchBlocks {
  public static void main(String[] args) {
    try {
      String input = args[0];
      // may throw ArrayIndexOutOfBoundsException
      int num = Integer.parseInt(input);
      // may throw NumberFormatException
      int result = 100 / num;
      // may throw ArithmeticException
      System.out.println("Result = " + result);
    } catch(ArrayIndexOutOfBoundsException e) {
      System.out.println("No argument passed: " + e);
    } catch(NumberFormatException e) {
      System.out.println("Not a number: " + e);
    } catch(ArithmeticException e) {
      System.out.println("Divide by zero: " + e);
    }
    System.out.println("After multiple catch blocks");
  }
}
// ------------------------------------------------------------------
// 5. Order matters - catch more specific exceptions first
// ------------------------------------------------------------------
class CatchOrder {
  public static void main(String[] args) {
    int[] arr = new int[2];
    try {
      arr[5] = 10;
    } catch(IndexOutOfBoundsException e) {
      // specific first
      System.out.println("IndexOutOfBoundsException: " + e);
    } catch(RuntimeException e) {
      // broader second
      System.out.println("RuntimeException caught");
    } catch(Exception e) {
      // broadest last
      System.out.println("Generic Exception caught");
    }
  }
}
// ------------------------------------------------------------------
// 6. try-catch with a finally block (multiple catches + finally)
// ------------------------------------------------------------------
class MultiCatchFinally {
  public static void main(String[] args) {
    try {
      int[] numbers = {
        1,2, 3
      }
      ;
      System.out.println(numbers[9]);
      // exception
    } catch(ArithmeticException e) {
      System.out.println("Arithmetic: " + e);
    } catch(ArrayIndexOutOfBoundsException e) {
      System.out.println("Array index: " + e);
    } finally {
      System.out.println("finally block executed");
    }
    System.out.println("Program ended normally");
  }
}
// ------------------------------------------------------------------
// 7. Multi-catch (Java 7+) - one block, multiple exception types
// ------------------------------------------------------------------
class MultiCatchJava7 {
  public static void main(String[] args) {
    try {
      String s = args[0];
      int n = Integer.parseInt(s);
      int[] a = new int[n];
      System.out.println(a[n]);
      // may throw any of the below
    } catch(ArrayIndexOutOfBoundsException | NumberFormatException e) {
      System.out.println("Caught (one of two types): " + e);
    }
  }
}

Session 3 - throw, throws, nested try-catch
Basic

Session 3 - throw, throws, nested try-catch
Topic: declaring exceptions with throws, throwing with throw,
rethrowing exceptions, the finally clause

// ============================================================
// Session 3 - throw, throws, nested try-catch
// Topic: declaring exceptions with throws, throwing with throw,
//        rethrowing exceptions, the finally clause
// ============================================================
// ------------------------------------------------------------------
// 1. Declaring exceptions - throws keyword
// ------------------------------------------------------------------
import java.io.*;
class ThrowsDemo {
  // Tells the caller: this method may throw IOException or SQLException
  public void myMethod() throws IOException, SQLException {
    FileReader reader = new FileReader("config.txt");
    System.out.println("Reading config...");
    reader.close();
  }
  public static void main(String[] args) {
    ThrowsDemo obj = new ThrowsDemo();
    try {
      obj.myMethod();
      // caller must handle the checked exception
    } catch(IOException | SQLException e) {
      System.out.println("Handled: " + e);
    }
  }
}
// ------------------------------------------------------------------
// 2. Throwing an exception - throw keyword
// ------------------------------------------------------------------
class ThrowDemo {
  public static void main(String[] args) {
    try {
      throw new IllegalArgumentException("Illegal argument passed");
    } catch(IllegalArgumentException e) {
      System.out.println("Caught: " + e.getMessage());
    }
  }
}
// ------------------------------------------------------------------
// 3. Declaring and throwing - setAge example (from PPT)
// ------------------------------------------------------------------
class AgeValidator {
  private int age;
  // declares it might throw, and throws when the condition fails
  public void setAge(int age) throws IllegalArgumentException {
    if(age > 0) this.age = age;
    else throw new IllegalArgumentException("Age cannot be negative or zero");
  }
  public int getAge() {
    return age;
  }
}
class AgeValidatorTest {
  public static void main(String[] args) {
    AgeValidator v = new AgeValidator();
    try {
      v.setAge(- 5);
      // triggers the throw
    } catch(IllegalArgumentException e) {
      System.out.println("Caught: " + e.getMessage());
    }
    v.setAge(25);
    // ok
    System.out.println("Age set to " + v.getAge());
  }
}
// ------------------------------------------------------------------
// 4. Rethrowing exceptions
// ------------------------------------------------------------------
class RethrowDemo {
  static void methodA() throws Exception {
    throw new Exception("original exception");
  }
  static void methodB() throws Exception {
    try {
      methodA();
    } catch(Exception ex) {
      System.out.println("Performing operations before exiting...");
      throw ex;
      // rethrow the same exception
    }
  }
  public static void main(String[] args) {
    try {
      methodB();
    } catch(Exception e) {
      System.out.println("Caught at top level: " + e.getMessage());
    }
  }
}
// ------------------------------------------------------------------
// 5. The finally clause - always executes
// ------------------------------------------------------------------
class FinallyClause {
  public static void main(String[] args) {
    int result = divide(10, 0);
    System.out.println("Result = " + result);
  }
  static int divide(int a, int b) {
    try {
      return a / b;
    } catch(Exception ex) {
      System.out.println("Exception: " + ex);
    } finally {
      System.out.println("finally: resources cleaned up");
    }
    return - 1;
  }
}
// ------------------------------------------------------------------
// 6. Nested try-catch inside methods (deep examples)
// ------------------------------------------------------------------
class NestedTryCatch2 {
  public static void main(String[] args) {
    try {
      int num = Integer.parseInt("abc");
      // outer try
      try {
        int result = 10 / num;
        System.out.println(result);
      } catch(ArithmeticException e) {
        System.out.println("Inner catch: " + e);
      }
    } catch(NumberFormatException e) {
      System.out.println("Outer catch: " + e);
    }
    System.out.println("Done");
  }
}
// ------------------------------------------------------------------
// 7. finally without catch - still allowed
// ------------------------------------------------------------------
class FinallyWithoutCatch {
  public static void main(String[] args) throws IOException {
    // try + finally (no catch) - exceptions propagate but finally runs
    try {
      FileWriter fw = new FileWriter("log.txt");
      fw.write("hello");
      fw.close();
      System.out.println("File written");
    } finally {
      System.out.println("finally always runs");
    }
  }
}

Session 4 - Try-with-Resources and Custom Exceptions
Basic

Session 4 - Try-with-Resources and Custom Exceptions
Topic: try-with-resources (single & multiple resources, finally),
custom / user-defined exceptions

// ============================================================
// Session 4 - Try-with-Resources and Custom Exceptions
// Topic: try-with-resources (single & multiple resources, finally),
//        custom / user-defined exceptions
// ============================================================
// ------------------------------------------------------------------
// 1. Try-with-resources - single resource (FileOutputStream)
// ------------------------------------------------------------------
import java.io.FileOutputStream;
class TryWithResources {
  public static void main(String[] args) {
    // resource is declared inside try(...) and auto-closed
    try(FileOutputStream fos = new FileOutputStream("abc.txt")) {
      String msg = "WELCOME BACK!";
      byte[] byteArray = msg.getBytes();
      fos.write(byteArray);
      System.out.println("Message written to file successfully!");
    } catch(Exception exception) {
      System.out.println(exception);
    }
  }
}
// ------------------------------------------------------------------
// 2. Try-with-resources - multiple resources (write then read)
// ------------------------------------------------------------------
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
class TryWithResourcesMultiple {
  public static void main(String[] args) {
    try(FileOutputStream fos = new FileOutputStream("abc.txt"); InputStream input = new FileInputStream("abc.txt")) {
      String msg = "Welcome to javaTpoint!";
      byte[] byteArray = msg.getBytes();
      fos.write(byteArray);
      System.out.println("------------Data written into file--------------");
      System.out.println(msg);
      DataInputStream inst = new DataInputStream(input);
      int data = input.available();
      byte[] byteArray2 = new byte[data];
      inst.read(byteArray2);
      String str = new String(byteArray2);
      System.out.println("------------Data read from file--------------");
      System.out.println(str);
    } catch(Exception exception) {
      System.out.println(exception);
    }
  }
}
// ------------------------------------------------------------------
// 3. Try-with-resources with finally block
// ------------------------------------------------------------------
class TryWithResourcesFinally {
  public static void main(String[] args) {
    try(FileOutputStream fos = new FileOutputStream("abc.txt")) {
      String msg = "Welcome to javaTpoint!";
      byte[] byteArray = msg.getBytes();
      fos.write(byteArray);
      System.out.println("Data written successfully!");
    } catch(Exception exception) {
      System.out.println(exception);
    } finally {
      System.out.println("Finally executes after closing of declared resources.");
    }
  }
}
// ------------------------------------------------------------------
// 4. Custom Exception - InvalidAgeException (from PPT)
// ------------------------------------------------------------------
class InvalidAgeException extends Exception {
  public InvalidAgeException(String str) {
    super(str);
  }
}
class TestCustomException1 {
  static void validate(int age) throws InvalidAgeException {
    if(age < 18) {
      throw new InvalidAgeException("age is not valid to vote");
    } else {
      System.out.println("welcome to vote");
    }
  }
  public static void main(String[] args) {
    try {
      validate(13);
    } catch(InvalidAgeException ex) {
      System.out.println("Caught the exception");
      System.out.println("Exception occured: " + ex);
    }
    System.out.println("rest of the code...");
  }
}
// ------------------------------------------------------------------
// 5. Simple custom exception - MyCustomException
// ------------------------------------------------------------------
class MyCustomException extends Exception {
}
class TestCustomException2 {
  public static void main(String[] args) {
    try {
      throw new MyCustomException();
    } catch(MyCustomException ex) {
      System.out.println("Caught the exception");
      System.out.println(ex.getMessage());
    }
    System.out.println("rest of the code...");
  }
}
// ------------------------------------------------------------------
// 6. Business-logic custom exception with more detail
// ------------------------------------------------------------------
class InsufficientFundsException extends Exception {
  private double shortfall;
  public InsufficientFundsException(double amount, double balance) {
    super("Insufficient funds: needed " + amount + ", available " + balance);
    this.shortfall = amount - balance;
  }
  public double getShortfall() {
    return shortfall;
  }
}
class BankAccount {
  private double balance;
  public BankAccount(double balance) {
    this.balance = balance;
  }
  public void withdraw(double amount) throws InsufficientFundsException {
    if(amount > balance) {
      throw new InsufficientFundsException(amount, balance);
    }
    balance -= amount;
    System.out.println("Withdrew " + amount + ", balance " + balance);
  }
}
class CustomExceptionBusiness {
  public static void main(String[] args) {
    BankAccount acct = new BankAccount(1000);
    try {
      acct.withdraw(5000);
    } catch(InsufficientFundsException e) {
      System.out.println(e.getMessage());
      System.out.println("Shortfall = " + e.getShortfall());
    }
  }
}
// ------------------------------------------------------------------
// 7. AutoCloseable - custom resource usable with try-with-resources
// ------------------------------------------------------------------
class DatabaseConnection implements AutoCloseable {
  DatabaseConnection() {
    System.out.println("Connection opened");
  }
  void query(String sql) {
    System.out.println("Running: " + sql);
  }
  @Override public void close() {
    System.out.println("Connection closed automatically");
  }
}
class AutoCloseableDemo {
  public static void main(String[] args) {
    try(DatabaseConnection conn = new DatabaseConnection()) {
      conn.query("SELECT * FROM users");
    }
    // close() called automatically here
    System.out.println("Try-with-resources finished");
  }
}

Creating custom exception
Basic

Creating custom exception

package vs.exception;
public class AgeException extends ArithmeticException {
  String message;
  public AgeException() {
    super("Age is less than or equal to 0");
  }
  public AgeException(String message) {
    super(message);
  }
  public String toString() {
    return message;
  }
}
Video Lesson Open in new tab
Quiz
1. Which of the following is a checked exception in Java?
2. Which keyword is used to handle exceptions in Java?
3. What happens if a try block has no catch block?
4. Which block always gets executed whether an exception occurs or not?
5. What is the parent class of all exceptions in Java?
6. Which of the following is an unchecked exception?
7. Can we have multiple catch blocks for a single try block?
8. What is the difference between throw and throws?
9. What is a custom exception in Java?
10. In which scenario does the finally block NOT execute?
Coding Problems
1. Write a Java program that defines a custom InvalidAgeException extending Exception and a validate(int age) method that throws it when age is below 18; catch it in main and print the message.
Discussion

Login to join the discussion.


No comments yet.