
জাভা শেখার শুরুতে সবচেয়ে বেশি হতাশা তৈরি করে কনসোলের লাল রঙের কয়েকটা লাইন। প্রোগ্রাম লিখলেন, রান করলেন, আর ভেসে উঠল Exception in thread main java.lang.NullPointerException। অনেকে এই জায়গায় এসে কোড এলোমেলোভাবে ঘাঁটতে শুরু করেন, কেউ আবার পুরো কোডের চারপাশে try catch বসিয়ে এররটা চোখের আড়াল করে ফেলেন। কিন্তু সমস্যাটা তখনো রয়ে যায়, শুধু আর দেখা যায় না। কিছুদিন পর সেই লুকানো সমস্যাই বড় আকারে ফিরে আসে।
সত্যি বলতে গেলে ওই লাল লেখাগুলোই জাভার সবচেয়ে সাহায্যকারী অংশ। সেখানে হুবহু লেখা থাকে কোন ক্লাসের কোন লাইনে সমস্যা হয়েছে এবং কোন মেথড কাকে ডেকেছিল। এই টিউনে তত্ত্ব মুখস্থ করার বদলে আমরা ইচ্ছা করে পাঁচটি কমন এরর তৈরি করব, প্রতিটির স্ট্যাক ট্রেস লাইন ধরে পড়ব, তারপর কোড ঠিক করব। শেষে জানব try catch finally এবং try with resources এর সঠিক ব্যবহার কোথায়, আর নিজের Custom Exception কীভাবে বানাতে হয়।
প্রোগ্রাম চলার সময় অস্বাভাবিক কিছু ঘটলে JVM একটি অবজেক্ট তৈরি করে, যার নাম Exception। এই অবজেক্টটি যে মেথডে সমস্যা হয়েছে সেখান থেকে উপরের দিকে উঠতে শুরু করে, অর্থাৎ যে মেথড তাকে ডেকেছিল তার কাছে যায়। সেখানেও ধরার ব্যবস্থা না থাকলে আরও উপরে ওঠে। কোথাও ধরা না পড়লে থ্রেডটি বন্ধ হয়ে যায় এবং কনসোলে পুরো ভ্রমণপথ ছাপা হয়। এই ছাপা তালিকাটির নামই স্ট্যাক ট্রেস।
নিচের স্ট্যাক ট্রেসটি মন দিয়ে দেখুন। এটি পড়তে হয় উপর থেকে নিচে, আর কাজের তথ্যটুকু থাকে প্রথম দুই লাইনেই।
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "name" is null at com.example.ErrorLab.printLength(ErrorLab.java:16) at com.example.ErrorLab.main(ErrorLab.java:6)
নিচের কোডটি ErrorLab.java নামে সেভ করে রান করুন। এখানে findUser মেথডটি ব্যবহারকারী না পেলে null ফেরত দিচ্ছে, আর সেই null এর উপরেই length মেথড ডাকা হচ্ছে।
public class ErrorLab {public static void main(String[] args) {String name = findUser(101); printLength(name);} static String findUser(int id) {if (id = 100) {return "Nasirul";} return null;} static void printLength(String name) {System.out.println(name.length());} static void printLength(String name) {if (name = null) {System.out.println("ইউজার পাওয়া যায়নি"); return;} System.out.println(name.length());}অ্যারের ঘর গোনা শুরু হয় শূন্য থেকে, তাই তিন ঘরের অ্যারের সর্বশেষ ইনডেক্স দুই। নিচের লুপে সমান চিহ্ন ব্যবহার করার কারণে প্রোগ্রামটি চার নম্বর ঘরে হাত দিতে চাইছে।
int[] marks = {70, 85, 90};
for (int i = 0; i <= marks.length; i+) {System.out.println(marks[i]);}ব্যবহারকারীর দেওয়া লেখা সংখ্যায় রূপ দিতে গিয়ে এই এররটি সবচেয়ে বেশি ঘটে। লেখাটির ভেতরে একটি অক্ষর বা ফাঁকা জায়গা থাকলেই parseInt আর কাজ করে না।
String input = "12a"; int value = Integer.parseInt(input); System.out.println(value);
try {int value = Integer.parseInt(input.trim()); System.out.println("সংখ্যাটি " + value);} catch (NumberFormatException e) {System.out.println("শুধু সংখ্যা লিখুন, আপনি লিখেছেন " + input);}পূর্ণসংখ্যাকে শূন্য দিয়ে ভাগ করলে জাভা ArithmeticException ছোড়ে। মজার বিষয় হলো দশমিক সংখ্যার ক্ষেত্রে এররের বদলে Infinity আসে, তাই গড় হিসাবের কোডে ভুলটি অনেক সময় চোখে পড়ে না।
int total = 250; int count = 0; int average = total / count;
এবার ClassCastException দেখুন। একটি অবজেক্টকে জোর করে ভুল টাইপে রূপ দিতে চাইলে এই এররটি আসে।
Object obj = "Techtunes"; Integer number = (Integer) obj;
if (obj instanceof Integer number) {System.out.println(number + 10);} else {System.out.println("এটি সংখ্যা নয়");}finally ব্লকের কোড এররে হোক বা না হোক চলবেই, তাই আগে এখানে ফাইল বা ডেটাবেজ বন্ধ করার কাজ লেখা হতো। এখন সেই কাজটি try with resources নিজেই করে দেয়, ফলে বন্ধ করতে ভুলে যাওয়ার ঝুঁকি থাকে না।
try (BufferedReader reader = new BufferedReader(new FileReader("marks.txt"))) {String line = reader.readLine(); System.out.println(line);} catch (IOException e) {System.out.println("ফাইল পড়া যায়নি, কারণ " + e.getMessage());}প্রজেক্ট বড় হলে নিজের নিয়ম অনুযায়ী Exception বানালে কোড পড়তে সুবিধা হয়। নিচের উদাহরণে নম্বর যাচাইয়ের জন্য একটি আলাদা Exception তৈরি করা হয়েছে।
class InvalidMarkException extends RuntimeException {public InvalidMarkException(String message) {super(message);}
static void checkMark(int mark) {if (mark < 0 | mark > 100) {throw new InvalidMarkException("নম্বর ০ থেকে ১০০ এর মধ্যে হতে হবে, পাওয়া গেছে " + mark);} System.out.println("নম্বর ঠিক আছে");}এমন হলে তালিকার নিচের দিকে তাকান এবং প্যাকেজের নাম দিয়ে খুঁজুন। লাইব্রেরির ভেতরের লাইনগুলো বাদ দিয়ে নিজের প্যাকেজের প্রথম যে লাইনটি পাবেন, ভুলটি সেখানেই আছে।
catch ব্লকে যে Exception ধরেছেন সেটি হয়তো আসল Exception এর মূল ক্লাস নয়। কনসোলের লেখা নাম হুবহু মিলিয়ে নিন, প্রয়োজনে একই try এর সাথে একাধিক catch ব্লক ব্যবহার করুন।
এডিটরে ব্রেকপয়েন্ট বসিয়ে ডিবাগ মোডে চালান এবং Variables প্যানেলে দেখুন কোন রেফারেন্সের মান null। IntelliJ IDEA তে Run মেনু থেকে ভিউ প্যানেলে Exception Breakpoint যোগ করলে এরর ঘটার ঠিক মুহূর্তেই প্রোগ্রাম থেমে যায়।
Exception আপনার শত্রু নয়, বরং সবচেয়ে সৎ পরামর্শদাতা। যে মুহূর্তে আপনি স্ট্যাক ট্রেসের প্রথম দুই লাইন পড়তে শিখে যাবেন, সেই মুহূর্ত থেকে ডিবাগিংয়ের সময় কয়েক গুণ কমে যাবে। আজ যে পাঁচটি এরর নিয়ে কাজ করলাম, সেগুলো ইচ্ছা করে আরও কয়েকবার তৈরি করুন এবং প্রতিবার স্ট্যাক ট্রেস পড়ে নিজে নিজে জায়গাটি বের করার অভ্যাস গড়ুন।
আপনি জাভা শিখতে গিয়ে কোন এররটিতে সবচেয়ে বেশি সময় নষ্ট করেছেন, টিউমেন্টে জানান। পরের টিউনে আমরা একটি সম্পূর্ণ প্রজেক্ট বানাব যেখানে এই ধরনের সমস্যা হাতে কলমে সমাধান করা হবে।
আমি নাছিরুল হক। বিশ্বের সর্ববৃহৎ বিজ্ঞান ও প্রযুক্তির সৌশল নেটওয়ার্ক - টেকটিউনস এ আমি 13 ঘন্টা 33 মিনিট যাবৎ যুক্ত আছি। টেকটিউনস আমি এ পর্যন্ত 6 টি টিউন ও 0 টি টিউমেন্ট করেছি। টেকটিউনসে আমার 0 ফলোয়ার আছে এবং আমি টেকটিউনসে 0 টিউনারকে ফলো করি।