একজন জাভা ডেভেলপার হিসেবে, আপনার জাভা এক্সেপশন এবং এক্সেপশন হ্যান্ডলিং সম্পর্কে ভালো জ্ঞান থাকা উচিত।
এই টিউটোরিয়ালটি প্রতিটি প্রোগ্রামারের জন্য জাভা প্রোগ্রাম নিয়ে কাজ করার সময় জানা প্রয়োজনীয় বেসিক জ্ঞান প্রদান করে। শুরু করার আগে, আসুন বুঝি জাভা এক্সেপশন আসলে কী।
জাভা এক্সেপশন কী?
একটি জাভা প্রোগ্রাম এক্সিকিউশনের সময় সমস্যায় পড়তে পারে যার ফলে প্রোগ্রাম হঠাৎ বন্ধ হয়ে যায়। এই সমস্যাগুলোকে এক্সেপশন বলা হয়।
একজন ভালো প্রোগ্রামার এক্সিকিউশনের সময় ঘটতে পারে এমন এররগুলো আগে থেকে চিনতে পারবেন এবং এমন এক্সেপশন হলে প্রোগ্রামের জন্য বিকল্প পথ প্রদান করবেন। এই প্র্যাকটিসকে এক্সেপশন হ্যান্ডলিং বলা হয়।
আপনি চিন্তা করতে পারেন এক্সেপশন হ্যান্ডলিং কেন দরকার। কেন না এমন প্রোগ্রাম লিখা যেতে পারে যেগুলো এক্সেপশন থ্রো করবে না?
এক্সেপশন হ্যান্ডলিং কেন দরকার?
বাস্তবে, এক্সেপশন থ্রো না করা এমন প্রোগ্রাম লিখা শুনতে সহজ কিন্তু বাস্তবে ততো সহজ নয়। অধিকাংশ সময় এই এড়ানো না যায় এমন এররগুলো প্রোগ্রামারের কন্ট্রোলের বাইরে থাকে।
যে প্রোগ্রামগুলো ইউজার ইনপুট গ্রহণ করে, সেগুলো এক্সেপশনে পড়ার চান্স বেশি কারণ ইউজার ইনভ্যালিড ইনপুট দিতে পারে। এক্সটার্নাল ফাইল পড়ার জন্যও এক্সেপশন হতে পারে কারণ সেগুলো প্রোগ্রামারের জানা ছাড়া সরানো, রিনেম করা বা ডিলিট করা হতে পারে।
এই কেসগুলোতে, প্রোগ্রামটি এক্সিকিউশন বন্ধ না করে গ্রেসফুলি এক্সেপশন হ্যান্ডল করতে প্যারা হবে।
জাভা এক্সেপশন হায়ারার্কি
জাভার সকল এক্সেপশন Exception ক্লাসের চাইল্ড হতে হবে, যা নিজে Throwable ক্লাসের চাইল্ড।
Exception ক্লাসের দুটি প্রধান সাবক্লাস হল RuntimeException এবং IOException।
এक्सেপশন বনাম এরর
Throwable ক্লাসের আরেকটি চাইল্ড ক্লাস হল Error ক্লাস। কিন্তু এরর এক্সেপশন থেকে আলাদা।
এরর নির্দেশ করে JVM এক্সিকিউশনের সময় যে সমস্যাগুলোতে পড়তে পারে। এই সমস্যাগুলো সাধারণত ক্রিটিক্যাল এবং অনরিকভারেবল। মেমরি লিক এবং লাইব্রেরি ইনকম্প্যাটিবিলিটি ইস্যু প্রোগ্রামে এররের সাধারণ কারণ।
StackOverflowError এবং OutOfMemoryError জাভা এররের দুটি উদাহরণ।
চেকড এবং আনচেকড এক্সেপশন
জাভা এক্সেপশনকে দুটি প্রধান ক্যাটাগরিতে ভাগ করা যায়: চেকড এবং আনচেকড এক্সেপশন।
চেকড এক্সেপশন হল সেই এক্সেপশনগুলো যেগুলো কম্পাইল করার আগে প্রোগ্রামে হ্যান্ডল করা আবশ্যক। যদি এই এক্সেপশনগুলো হ্যান্ডল না করা হয়, তবে জাভা কম্পাইলার প্রোগ্রাম কম্পাইল করবে না। তাই এগুলোকে কম্পাইল-টাইম এক্সেপশনও বলা হয়। IOExceptions চেকড এক্সেপশনের ভালো উদাহরণ।
আনচেকড এক্সেপশন হল সেই এক্সেপশনগুলো যেগুলো কম্পাইলার কম্পাইল করার সময় উপেক্ষা করে। প্রোগ্রামে এগুলো হ্যান্ডল করা হয়েছে কিনা সেটি কম্পাইলেশনের সময় কোনো মАнস করে না। যেহেতু এই এক্সেপশনগুলোর জন্য হ্যান্ডলিং বাধ্যতামূলক নয়, তাই আমাদের প্রোগ্রাম RuntimeExceptions-এ পড়তে পারে যা প্রোগ্রাম টার্মিনেট করবে।
RuntimeException ক্লাস এক্সটেন্ড করা সকল ক্লাস আনচেকড এক্সেপশন। এর দুটি উদাহরণ হল NullPointerException এবং ArrayIndexOutOfBoundsException।
Exception ক্লাসে সাধারণত ব্যবহৃত মেথড
জাভা Exception ক্লাসের কিছু সাধারণ মেথড দেখি:
getMessage: ঘটনাক্রমে এক্সেপশন সম্পর্কে ডিটেইলস সহ একটি মেসেজ রিটার্ন করে।printStackTrace: ঘটনাক্রমে এক্সেপশনের স্ট্যাক ট্রেস রিটার্ন করে।toString: ক্লাসের নাম এবংgetMessageমেথড থেকে রিটার্ন হওয়া মেসেজ রিটার্ন করে।
এক্সেপশন কীভাবে হ্যান্ডল করবেন
আসুন দেখি জাভাতে এক্সেপশন কীভাবে হ্যান্ডল করা যায়:
try-catch
জাভাতে try-catch ব্লক ব্যবহার করে আমরা এক্সেপশন ক্যাচ এবং সঠিকভাবে হ্যান্ডল করতে পারি।
এই সিনট্যাক্সে, কোডের যে অংশটি এক্সেপশন থ্রো করতে পারে সেটি try ব্লকের ভিতরে রাখা হয় এবং catch ব্লক/ব্লকগুলো থ্রো হওয়া এক্সেপশন/এক্সেপশনগুলো ক্যাচ করে এবং আমাদের প্রদত্ত লজিক অনুযায়ী হ্যান্ডল করে।
try-catch ব্লকের বেসিক সিনট্যাক্স নিচে দেওয়া হলো:
try {
// এক্সেপশন-প্রোন কোড
} catch (Exception e) {
// এরর হ্যান্ডলিং লজিক
}
এই অ্যাপ্রোছ দিয়ে, প্রোগ্রাম এক্সেপশন থ্রো করলে এক্সিকিউশন হাল্ট না করে, বরং সেটি গ্রেসফুলি হ্যান্ডল হয়।
আসুন দেখি FileReader ক্লাস থ্রো হওয়া IOExceptions কীভাবে একটি জাভা প্রোগ্রামে হ্যান্ডল করা যায়।
উদাহরণ:
import java.io.FileReader;
public class TryCatchBlockExample {
public static void main(String[] args) {
try {
FileReader file = new FileReader("source.txt");
file.read();
} catch (Exception e) {
e.printStackTrace();
}
}
}
এখানে, আমরা একটি সিঙ্গেল catch ব্লক ব্যবহার করেছি FileReader ক্লাস ইনস্ট্যানশিয়েট করার সময় থ্রো হওয়া FileNotFoundException এবং FileReader ক্লাসের read() মেথড থ্রো হওয়া IOException হ্যান্ডল করার জন্য।
এই দুটি এক্সেপশনই Exception ক্লাসের চাইল্ড।
আমরা একাধিক catch স্টেটমেন্টও ব্যবহার করতে পারি একটি সিঙ্গেল try স্টেটমেন্টের ভিতরের কোড থ্রো করা ভিন্ন টাইপের এরর ক্যাচ করার জন্য। আগের উদাহরণের জন্য, আমরা একটি catch ব্লক ব্যবহার করতে পারি FileNotFoundException ক্যাচ করার জন্য এবং আরেকটি IOException এর জন্য নিচের কোড স্নিপেটটি দেখায়:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class TryCatchBlockExample {
public static void main(String[] args) {
try {
FileReader file = new FileReader("source.txt");
file.read();
file.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
যদি থ্রো হওয়া এক্সেপশন প্রথম catch স্টেটমেন্টের হ্যান্ডল করা এক্সেপশনের সাথে ম্যাচ করে, তবে সেটি প্রথম catch স্টেটমেন্টের ভিতরের লজিক দ্বারা হ্যান্ডল হয়।
যদি এক্সেপশনগুলো ম্যাচ না করে, তবে সেটি দ্বিতীয় catch স্টেটমেন্টে পাস হয়। যদি দুইটির অধিক catch স্টেটমেন্ট থাকে, তবে এই প্রক্রিয়া तबতেই চলবে যতক্ষণ না এক্সেপশন তার টাইপ ক্যাচ করা একটি catch স্টেটমেন্টে পৌঁছায়।
যেহেতু FileNotFoundException হল IOException এর সাবটাইপ, তাই ২য় catch স্টেটমেন্ট ব্যবহার করে FileNotFoundException ক্যাচ করা কাজ করবে না। সেটি প্রথম catch স্টেটমেন্ট দ্বারা হ্যান্ডল হবে এবং ২য় স্টেটমেন্টে কখনো পৌঁছাবে না।
নোট: একটি try স্টেটমেন্টের সাথে কমপক্ষে একটি catch স্টেটমেন্ট ব্যবহার করা বাধ্যতামূলক।
finally
যখন আমরা try-catch ব্লক ব্যবহার করে আমাদের প্রোগ্রামে এক্সেপশন ক্যাচ করি, তখন কিছু উদাহরণ থাকে যেটা আমরা এক্সেপশন ক্যাচ হয়েছে কিনা সেটি নির্বিশেষে কিছু লজিক ইমপ্লিমেন্ট করতে চাই। সেসব কেসে, আমরা শুধু try-catch ব্লকের পরিবর্তে try-catch-finally ব্লক ব্যবহার করতে পারি।
তখন, finally স্টেটমেন্টের ভিতরের কোড এক্সেপশন ঘটে কিনা সেটি নির্বিশেষে ইমপ্লিমেন্ট হয়। finally স্টেটমেন্টটি try-catch-finally ব্লকের শেষে থাকা উচিত।
উদাহরণস্বরূপ, যখন আমরা একটি ফাইল পড়তে FileReader ক্লাস ব্যবহার করি, তখন প্রসেসিংয়ের শেষে খোলা ফাইলটি বন্ধ করা অত্যন্ত জরুরি এক্সেপশন হয়েছে কিনা সেটি নির্বিশেষে। এটি নিশ্চিত করতে, আমরা ফাইল বন্ধ করার কোডটি একটি finally স্টেটমেন্টের ভিতরে রাখতে পারি।
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class TryCatchFinallyBlockExample {
public static void main(String[] args) {
FileReader file = null;
try {
file = new FileReader("source.txt");
file.read();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
file.close();
}
}
}
তবে, আপনি যদি উপরের কোড কম্পাইল করার চেষ্টা করেন, তবে কোড কম্পাইল হবে না একটি অনহ্যান্ডলড IOException এর কারণে। এর কারণ হল FileReader ক্লাসের close() মেথডও IOExceptions থ্রো করতে পারে। তাই, আমাদের এই অংশটিকে অন্য একটি try ব্লকের ভিতরে রাখতে হবে:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class TryCatchFinallyBlockExample {
public static void main(String[] args) {
FileReader file = null;
try {
file = new FileReader("source.txt");
file.read();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
throws
জাভাতে throws কীওয়ার্ড ব্যবহার করে এরর হ্যান্ডলিং সিম্পল। আসলে, এই অ্যাপ্রোছতে, আপনি এক্সেপশনটি সেটি ঘটে যে জায়গায় সেখানে হ্যান্ডল করেন না। বরং, আমরা এক্সেপশনটি করেন্ট মেথড থেকে কলিং মেথডে থ্রো করি। তারপর, এরর হ্যান্ডলিং বাইরের মেথডের দায়িত্ব হয়।
একটি মেথড থেকে এক্সেপশন থ্রো করতে, আপনাকে শুধু ডিক্লেয়ার করতে হবে যে এই মেথডটি বিবেচিত এক্সেপশন থ্রো করতে পারে। আসুন দেখি FileReader ক্লাস থ্রো হওয়া IOExceptions কীভাবে এই অ্যাপ্রোছ দিয়ে হ্যান্ডল করা যায়।
উদাহরণ:
import java.io.FileReader;
import java.io.IOException;
public class ThrowsExample {
public void readFile() throws IOException {
FileReader file = new FileReader("source.txt");
file.read();
file.close();
}
}
throw
এই লিস্টের অন্যান্য অ্যাপ্রোছের বিপরীতে, throw কীওয়ার্ড এরর হ্যান্ডল করার জন্য ব্যবহৃত হয় না। কিন্তু যেহেতু অধিকাংশ লোক throw কীওয়ার্ডকে throws কীওয়ার্ডের সাথে গুলিয়ে ফেলে, তাই আমরা এখানে সেটি আলোচনা করব ভালো মনে হয়েছে।
throw কীওয়ার্ড ব্যবহার করা হয় এক্সপ্লিসিটলি একটি এক্সেপশন আহ্বান করার জন্য। আমরা একটি নতুন ইনস্ট্যানশিয়েটেড এক্সেপশন বা মেথডের ভিতরে ক্যাচ করা একটি এক্সেপশন থ্রো করতে পারি।
public class ThrowExample {
public void invalidate(int amount) throws Exception {
if (amount < 500) {
throw new Exception("Amount not sufficient");
}
}
}
ইউজার-ডিফাইনড এক্সেপশন
বিল্ট-ইন জাভা এক্সেপশন ব্যবহারের পাশাপাশি, আপনি আপনার নিজস্ব এক্সেপশন ডিফাইন করতে পারেন। আপনি সেগুলো চেকড বা আনচেকড এক্সেপশন হিসেবে ডিফাইন করতে পারেন। একটি নতুন চেকড এক্সেপশন তৈরি করতে, আপনার নতুন এক্সেপশনটি Exception ক্লাস এক্সটেন্ড করতে হবে।
একটি আনচেকড এক্সেপশন তৈরি করতে, RuntimeException ক্লাস এক্সটেন্ড করুন।
নিচের কোড উদাহরণে, আমরা একটি ইউজার-ডিফাইনড চেকড এক্সেপশন তৈরি করেছি:
public class InvalidLengthException extends Exception {
private int length;
private String message;
public InvalidLengthException(int length, String message) {
this.length = length;
this.message = message;
}
public int getAmount() {
return this.length;
}
public String getMessage() {
return this.message;
}
}
এখন আমরা উপরের এক্সেপশনটি আমাদের প্রোগ্রাম লজিকে এইভাবে ব্যবহার করতে পারি:
public class InputChecker {
private int minLength;
private int maxLength;
public InputChecker(int minLength, int maxLength) {
this.minLength = minLength;
this.maxLength = maxLength;
}
public void checkStringLength(String strInput) throws InvalidLengthException {
int strLength = strInput.length();
if (strLength < minLength) {
throw new InvalidLengthException(strLength, "Input should have minimum " + minLength + " characters");
} else if (strLength > maxLength) {
throw new InvalidLengthException(strLength, "Input should have maximum " + maxLength + " character");
}
}
}
যদি আমরা InputChecker ক্লাস ব্যবহার করে একটি স্ট্রিংয়ের দৈর্ঘ্য চেক করি, তবে স্ট্রিংয়ের দৈর্ঘ্য ন্যূনতম দৈর্ঘ্যের নিচে বা সর্বোচ্চ দৈর্ঘ্যের উপরে থাকলে এটি InvalidLengthException থ্রো করবে।
public class Main {
public static void main(String[] args) {
InputChecker ic = new InputChecker(2, 7);
try {
ic.checkStringLength("longer than the maximum length");
} catch (InvalidLengthException e) {
e.printStackTrace();
}
}
}
উপরের কোড স্নিপেটটি রান করলে, এটি একটি InvalidLengthException থ্রো করবে এবং আমরা নিচের আউটপুট পাব:
InvalidLengthException: Input should have maximum 7 character at InputChecker.checkStringLength(InputChecker.java:17) at Main.main(Main.java:6)
উপসংহার
এই টিউটোরিয়ালে, আমরা আপনাকে জাভা এক্সেপশন সংক্র সংক্ষিপ্ত ও সংক্ষিপ্ত পরিচয় দিয়েছি। আশা করি আপনি এখন এক্সেপশন কী এবং আপনার জাভা প্রোগ্রামে সেগুলো কীভাবে হ্যান্ডল করবেন সেটি ভালোভাবে বুঝতে পেরেছেন।