Lesson ১৩৭ মিনিট পড়া

এক্সেপশন হ্যান্ডলিং (Exception Handling)

আপনার প্রোগ্রাম ক্র্যাশ করার আগেই সমস্যাগুলো ধরুন এবং সামাল দিন

এক্সেপশন বা ব্যতিক্রম আসলে কী? (What Are Exceptions?)

ধরুন, আপনি রান্নার একটা রেসিপি অনুসরণ করছেন যেখানে লেখা আছে "২টি ডিম দিন"। কিন্তু আপনি দেখলেন যে ডিমের ট্রে-টা একদম খালি। এই অবস্থায় আপনি হয় ভয় পেয়ে রান্নাঘরে আগুন লাগিয়ে দিতে পারেন (প্রোগ্রাম ক্র্যাশ করা), অথবা খুব সুন্দরভাবে পরিস্থিতি সামাল দিতে পারেন — যেমন, ডিম ছাড়াই রান্নাটা সেরে নিতে পারেন অথবা দৌড়ে দোকানে গিয়ে ডিম কিনে আনতে পারেন। এক্সেপশন হ্যান্ডলিং (Exception Handling) আপনার কোডের জন্য ঠিক এই কাজটিই করে থাকে।

একটি এক্সেপশন (exception) হলো জাভার এমন একটি উপায়, যার মাধ্যমে সে বলে "অপ্রত্যাশিত কিছু একটা ঘটেছে।" যদি আপনি এই পরিস্থিতি সামাল না দেন বা হ্যান্ডল (handle) না করেন, তবে আপনার প্রোগ্রামটি একটি ভয়ংকর লাল রঙের এরর (error) মেসেজ দেখিয়ে বন্ধ হয়ে যাবে বা ক্র্যাশ করবে। কিন্তু সঠিকভাবে হ্যান্ডল করলে, আপনি সমস্যাটি ধরতে পারবেন এবং সে অনুযায়ী ব্যবস্থাও নিতে পারবেন।

জাভাতে মূলত দুটি বিভাগের এক্সেপশন রয়েছে:

  • চেকড এক্সেপশন (Checked exceptions) — জাভা এই সমস্যাগুলো আপনাকে সমাধান করতে বাধ্য করে (যেমন IOException)। কোডটিকে try/catch বা throws স্টেটমেন্টের সাহায্য ছাড়া কম্পাইলার রান বা চালাতেই দেবে না।
  • আনচেকড এক্সেপশন (Unchecked exceptions) — এগুলো হলো রানটাইমের (runtime) এমন সব সমস্যা, যেগুলো সমাধান করার জন্য জাভা আপনাকে বাধ্য করে না (যেমন NullPointerException, ArrayIndexOutOfBoundsException)। এগুলো সাধারণত আপনার কোডের ভেতর থাকা বাগ (bugs) বা ভুলের কারণে হয়ে থাকে।

Try / Catch / Finally

public class Main {
public static void main(String[] args) {
// Basic try-catch
try {
int result = 10 / 0; // this will throw ArithmeticException
System.out.println("Result: " + result); // never reached
} catch (ArithmeticException e) {
System.out.println("Oops! Can't divide by zero.");
System.out.println("Error: " + e.getMessage());
}
System.out.println("---");
// Multiple catch blocks
String[] names = {"Anika", "Rafi"};
try {
System.out.println(names[5]); // out of bounds!
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("That index doesn't exist!");
} catch (Exception e) {
System.out.println("Something else went wrong.");
}
System.out.println("---");
// Finally — runs NO MATTER WHAT
try {
int x = Integer.parseInt("abc"); // NumberFormatException
} catch (NumberFormatException e) {
System.out.println("That's not a number!");
} finally {
System.out.println("Finally block always runs.");
}
System.out.println("Program continues normally!");
}
}
Output
Oops! Can't divide by zero.
Error: / by zero
---
That index doesn't exist!
---
That's not a number!
Finally block always runs.
Program continues normally!

এক্সেপশন থ্রো করা এবং কাস্টম এক্সেপশন (Throwing Exceptions & Custom Exceptions)

মাঝেমধ্যে আপনি নিজেই হয়তো একটি এক্সেপশন থ্রো (throw) করতে চাইবেন। ধরুন, কেউ আপনার মেথডে বয়স হিসেবে একটি নেগেটিভ (negative) বা ঋণাত্মক সংখ্যা পাঠালো — এটি কোনোভাবেই যুক্তিযুক্ত নয়। তাই আপনি এই সমস্যাটির কথা জানাতে বা সতর্ক করতে একটি এক্সেপশন থ্রো (throw) করতে পারেন।

একটি এক্সেপশন ছুঁড়ে দিতে বা থ্রো করতে throw new ExceptionType("message") ব্যবহার করুন। মেথডটির সিগনেচারে (signature) throws ব্যবহার করে কলারদের (callers) সতর্ক করে দিন যে, এই মেথডটি চালালে একটি চেকড এক্সেপশন থ্রো হতে পারে।

আপনি চাইলে Exception (চেকড এক্সেপশনের জন্য) অথবা RuntimeException (আনচেকড এক্সেপশনের জন্য) ক্লাসগুলোকে এক্সটেন্ড (extend) করে আপনার নিজস্ব কাস্টম এক্সেপশন ক্লাসও (custom exception classes) তৈরি করতে পারেন।

Throw, Throws এবং কাস্টম এক্সেপশন (Throw, Throws & Custom Exceptions)

public class Main {
// Custom exception
static class InvalidAgeException extends Exception {
InvalidAgeException(String message) {
super(message);
}
}
// Method that throws our custom exception
static void setAge(String name, int age) throws InvalidAgeException {
if (age < 0) {
throw new InvalidAgeException("Age can't be negative: " + age);
}
if (age > 150) {
throw new InvalidAgeException("Age seems unrealistic: " + age);
}
System.out.println(name + "'s age set to " + age);
}
// Method that throws a built-in exception
static double divide(double a, double b) {
if (b == 0) {
throw new IllegalArgumentException("Cannot divide by zero!");
}
return a / b;
}
public static void main(String[] args) {
// Handle custom exception
try {
setAge("Anika", 25);
setAge("Rafi", -5);
} catch (InvalidAgeException e) {
System.out.println("Error: " + e.getMessage());
}
System.out.println("---");
// Handle built-in exception
try {
System.out.println("10 / 3 = " + divide(10, 3));
System.out.println("10 / 0 = " + divide(10, 0));
} catch (IllegalArgumentException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Output
Anika's age set to 25
Error: Age can't be negative: -5
---
10 / 3 = 3.3333333333333335
Error: Cannot divide by zero!

Tra-With-Resources

import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// Try-with-resources automatically closes resources
// Even if an exception occurs!
String data = "42\n3.14\nhello\n100";
try (Scanner scanner = new Scanner(data)) {
while (scanner.hasNext()) {
String token = scanner.next();
try {
int num = Integer.parseInt(token);
System.out.println("Integer: " + num);
} catch (NumberFormatException e1) {
try {
double d = Double.parseDouble(token);
System.out.println("Double: " + d);
} catch (NumberFormatException e2) {
System.out.println("String: " + token);
}
}
}
} // scanner is automatically closed here!
System.out.println("Scanner was auto-closed. Clean!");
}
}
Output
Integer: 42
Double: 3.14
String: hello
Integer: 100
Scanner was auto-closed. Clean!
Note: সোনালী নিয়ম: সাধারণ বা গ্লোবাল এক্সেপশনের বদলে নির্দিষ্ট বা স্পেসিফিক (specific) এক্সেপশন ক্যাচ (catch) করুনcatch (Exception e) লেখার মানে হলো, ডাক্তারের কাছে গেলে তিনি আপনার সমস্যা বিস্তারিত না শুনেই শুধু বলে দিলেন "আপনি অসুস্থ"। এর বদলে NumberFormatException, IOException ইত্যাদিকে ক্যাচ করুন, যাতে প্রতিটি সমস্যা আপনি আলাদাভাবে এবং সঠিকভাবে সামাল দিতে পারেন। সাধারণ Exception-কে কেবল একদম শেষ সম্বল বা সেফটি নেট (safety net) হিসেবে ব্যবহার করবেন।
চ্যালেঞ্জ

ছোট কুইজ

চেকড (checked) এবং আনচেকড (unchecked) এক্সেপশনের মধ্যে পার্থক্য কী?

পড়া চালিয়ে যান

GenericsFile I/O