Exception Handling & try-with-resources

Exception Handling — checked vs unchecked, try/catch/finally, এবং আধুনিক try-with-resources

Read: ~35 min Intermediate 5 practice problems Live code runner

1. What Is an Exception?

An exception is Java's way to say "I can't continue normally." When thrown, it unwinds the call stack until someone catches it, or until the program ends. Java distinguishes checked exceptions (the compiler forces you to handle or declare them) from unchecked ones (subclasses of RuntimeException) which typically indicate bugs.

Exception হলো Java-র "আর স্বাভাবিকভাবে চলতে পারছি না" বলার উপায়। Exception throw হলে call stack unwind হয়, যতক্ষণ না কেউ catch করে, বা প্রোগ্রাম শেষ হয়। Checked exception-এ compiler handle/declare বাধ্য করে; unchecked (RuntimeException-এর subclass) সাধারণত বাগ নির্দেশ করে।
Throwable Hierarchy Throwable Error (fatal) Exception Checked (IOException...) RuntimeException (unchecked) Figure 31.1 — Throwable হায়ারার্কি — Error vs Exception (checked vs unchecked)।

2. try / catch / finally

Wrap code that might throw in try; catch specific types in catch; put cleanup that must always run in finally.

exception ছোঁড়ার সম্ভাবনা থাকা code try-তে রাখুন; নির্দিষ্ট type ধরতে catch ব্লক; সব সময় চালানোর জন্য cleanup finally-তে।
Main.java
class Main {
    public static void main(String[] args) {
        int[] xs = { 10, 20, 30 };

        try {
            System.out.println(xs[5]);       // out of bounds
        } catch (ArrayIndexOutOfBoundsException ex) {
            System.out.println("bad index: " + ex.getMessage());
        } catch (RuntimeException ex) {
            System.out.println("other runtime problem: " + ex);
        } finally {
            System.out.println("cleanup always runs");
        }

        // Multi-catch
        try {
            Integer.parseInt("not-a-number");
        } catch (NumberFormatException | ArithmeticException ex) {
            System.out.println("parse/math error: " + ex.getClass().getSimpleName());
        }
    }
}

3. Checked vs Unchecked

AspectCheckedUncheckedবাংলায়
ParentExceptionRuntimeExceptionParent class আলাদা।
Compiler forceMust catch or declareNoChecked-এ compiler জোরে।
Typical causeExternal failure (I/O, network)Programming bugsবাহ্যিক ব্যর্থতা বনাম বাগ।
ExamplesIOException, SQLExceptionNullPointerException, IllegalArgumentExceptionদৃষ্টান্ত।
Guideline: use checked exceptions for recoverable, expected failure; use unchecked for programming errors. Never catch-and-ignore (catch (Exception e) {}).

নিয়ম: recoverable, expected ব্যর্থতায় checked; programming bug-এ unchecked। catch (Exception e) {} — কখনোই নয়।

4. try-with-resources (Java 7+)

Any resource that implements AutoCloseable can be declared in the try(...) header and will be closed automatically — even if an exception is thrown. This replaces noisy try/finally cleanup code.

যে resource AutoCloseable implement করে, তাকে try(...)-এর header-এ declare করলে Java নিজেই close করে — exception হলেও। এটি try/finally-র বিশৃঙ্খলা দূর করে।
Main.java
class Main {
    // Any AutoCloseable works — here a tiny in-memory resource for demo
    static class Scoped implements AutoCloseable {
        String name;
        Scoped(String n) { name = n; System.out.println("open " + n); }
        public void doWork() { System.out.println("work " + name); }
        @Override public void close() { System.out.println("close " + name); }
    }

    public static void main(String[] args) {
        // Resources close in reverse order at end of block — even on exception
        try (Scoped a = new Scoped("A");
             Scoped b = new Scoped("B")) {
            a.doWork();
            b.doWork();
            if (args.length == 42) throw new RuntimeException("boom");
        }
        System.out.println("after block");
    }
}

5. Custom Exception Classes

Define domain-specific exception types by extending RuntimeException (for unchecked) or Exception (for checked). Always preserve the original cause via the Throwable constructor — losing the cause is a common production-debugging trap.

নিজের domain-এর exception type বানাতে RuntimeException (unchecked) বা Exception (checked) extend করুন। মূল cause-কে Throwable-constructor-এ pass করে রাখুন — production debug-এ cause হারিয়ে ফেলা সবচেয়ে বড় ফাঁদ।
Main.java
class Main {

    static class InsufficientFundsException extends RuntimeException {
        final long shortfall;
        InsufficientFundsException(long shortfall, Throwable cause) {
            super("short by " + shortfall + " tk", cause);
            this.shortfall = shortfall;
        }
    }

    static void debit(long balance, long amount) {
        if (amount > balance) {
            throw new InsufficientFundsException(amount - balance, null);
        }
        System.out.println("debited " + amount + ", remaining " + (balance - amount));
    }

    public static void main(String[] args) {
        try {
            debit(1000, 500);
            debit(1000, 1500);
        } catch (InsufficientFundsException ex) {
            System.out.println("caught: " + ex.getMessage());
        }
    }
}

6. Vocabulary

TermMeaningবাংলায়
throwActively raise an exception.exception ছোঁড়ার keyword।
throwsMethod declares possible checked exceptions.Method declaration-এ possible checked exception।
finallyRuns whether or not an exception was thrown.exception যাই হোক, সব সময় চলে।
AutoCloseableInterface used by try-with-resources.try-with-resources-এর interface।
Stack tracePath of calls at the moment of failure.ব্যর্থতার মুহূর্তে call chain।
Cause chainNested exception revealing the root cause.মূল কারণ খুঁজে পাওয়ার exception চেইন।

7. Practice Problems

  1. Catch a NumberFormatException when parsing "abc" and print a friendly message.
    "abc" parse করতে গিয়ে NumberFormatException ধরে একটি বন্ধুত্বপূর্ণ message দিন।
    ✨ Show Answer
    Main.java
    class Main {
        public static void main(String[] args) {
            try {
                int n = Integer.parseInt("abc");
                System.out.println(n);
            } catch (NumberFormatException ex) {
                System.out.println("Please enter a valid number.");
            }
        }
    }
  2. Write a custom unchecked exception AgeInvalidException and throw it when age is negative.
    নিজে AgeInvalidException তৈরি করুন; age নেগেটিভ হলে throw করুন।
    ✨ Show Answer
    Main.java
    class Main {
        static class AgeInvalidException extends RuntimeException {
            AgeInvalidException(String msg) { super(msg); }
        }
        static void setAge(int a) {
            if (a < 0) throw new AgeInvalidException("age cannot be negative");
            System.out.println("age = " + a);
        }
        public static void main(String[] args) {
            setAge(22);
            try { setAge(-3); }
            catch (AgeInvalidException ex) { System.out.println("caught: " + ex.getMessage()); }
        }
    }
  3. Demonstrate try-with-resources with two AutoCloseable resources — show they close in reverse order.
    দুটি AutoCloseable resource দিয়ে try-with-resources দেখান; reverse order-এ close হয় এটা প্রমাণ করুন।
    ✨ Show Answer
    Main.java
    class Main {
        static class R implements AutoCloseable {
            String n;
            R(String n) { this.n = n; System.out.println("open " + n); }
            @Override public void close() { System.out.println("close " + n); }
        }
        public static void main(String[] args) {
            try (R a = new R("A"); R b = new R("B")) {
                System.out.println("inside block");
            }
        }
    }
  4. Explain when to use finally versus try-with-resources.
    finally কবে, try-with-resources কবে — পার্থক্য ব্যাখ্যা করুন।
    ✨ Show Answer

    Answer: Use try-with-resources whenever the resource implements AutoCloseable — files, sockets, DB connections, streams. It is shorter, exception-safe, and automatically suppresses exceptions from close() without losing the primary exception. Keep finally only for cleanup that is not a closable resource — e.g., restoring a ThreadLocal, logging a metric, or releasing a manual lock that doesn't implement AutoCloseable.

    Resource যদি AutoCloseable হয় (file, socket, DB connection, stream) — সব সময় try-with-resources। এটি ছোট, exception-safe, close()-এর exception-কে suppress করে মূল exception সংরক্ষণ করে। finally রাখুন শুধু সেই cleanup-এর জন্য যা resource নয় — যেমন ThreadLocal reset, metric log, বা manual lock release যেটি AutoCloseable নয়।

  5. Wrap a lower-level IOException into a domain ReportFailedException preserving the cause.
    নিচু স্তরের IOException-কে domain-level ReportFailedException-এ wrap করুন; cause হারাবেন না।
    ✨ Show Answer
    Main.java
    import java.io.*;
    
    class Main {
        static class ReportFailedException extends RuntimeException {
            ReportFailedException(String m, Throwable cause) { super(m, cause); }
        }
    
        static void buildReport() {
            try {
                throw new IOException("disk full");
            } catch (IOException ex) {
                throw new ReportFailedException("could not write daily report", ex);
            }
        }
    
        public static void main(String[] args) {
            try {
                buildReport();
            } catch (ReportFailedException ex) {
                System.out.println("top level: " + ex.getMessage());
                System.out.println("root cause: " + ex.getCause());
            }
        }
    }

Summary — Module 31

Java separates checked exceptions (must be declared or handled) from unchecked (RuntimeException). Use try/catch/finally for general flow, but prefer try-with-resources for anything that implements AutoCloseable — it closes resources in reverse order even when an exception is thrown. Build domain-specific exception types and always preserve the cause when wrapping.

Java-তে checked exception declare/handle করতেই হবে; unchecked (RuntimeException) সাধারণত বাগ বোঝায়। try/catch/finally আছে, কিন্তু AutoCloseable resource-এ সব সময় try-with-resources — exception হলেও reverse order-এ close হয়। নিজের domain exception class বানান, এবং wrap-এর সময় মূল cause সব সময় pass করুন।

Next Module → File I/O ও NIO.2 — আধুনিক Java-তে file-এর সাথে কাজ।