পাঠ ৬: জাভা এক্সেপশান হ্যান্ডেলিং
এক্সেপশান বেসিকস
ট্রাই ক্যাচ- ফাইনালি
চেকড-একসেপশান
আনচেকড-একসেপশান
থ্রুয়িং একসেপশান
NullPointerException
ArrayIndexOutOfBoundsException
কিভাবে নিজস্ব এক্সেপশান লিখবো
সারসংক্ষেপ
আমরা একটি প্রোগ্রাম লিখি যার একটি নরমাল ফ্লো থাকে, তবে কোন কারণে যদি এই ফ্লো ব্যাহত হয় তাহলে জাভা রানটাইম একটি ইভেন্ট ফায়ার করে, একে এক্সেপশান বলা হয়।
সহজ কথায় এক্সেপশন হচ্ছে এক ধরণের ইরর যা কিনা প্রোগ্রাম চলাকালীন সময়ে দেখা দিতে পারে ।
একটি উদাহরণ দেখা যাক-
১. এখানে divide()
মেথডটিতে a এবং b আর্গুমেন্ট পাস করা হলে মেথডটি প্রথম আর্গুমেন্টকে দ্বিতীয় আর্গুমেন্ট দিয়ে ভাগ করে ফলাফল result
ভ্যারিয়েবল-টিতে এসাইন করবে।
২. এখানে result
এর মান প্রিন্ট করা হবে।
আমরা যদি এই প্রোগ্রামটি রান করি তাহলে console এ নিচের আউটপুট-টি পাবো-
এই আউটপুট থেকে আমরা বুঝতে পারি যে, আমাদের প্রোগ্রামটি-তে একটি সমস্যা হয়েছে এবং প্রোগ্রামটি এখানেই থেমে গেছে, System.out.println("Result: " + result);
এই লাইনটি এক্সিকিউট হয় নি।
এবার আমরা নিচের প্রোগ্রামটি রান করি-
এবার console এ নিচের আউটপুটটি দেখবো -
You can't divide 1 by 0
Result: 0
এবার লক্ষ্য করুন। প্রোগ্রামটি কিন্তু থেমে যাই নি, বরং শুণ্য দিয়ে যে কোন সংখ্যাকে ভাগ করা যাবে না, তার জন্য একটি মেসেস প্রিন্ট করেছে এবং শেষ পর্যন্ত প্রত্যেকটি লাইন এক্সিকিউট হয়েছে।
এই প্রোগ্রামটিতে আমরা নতুন কিওয়ার্ড ব্যবহার করেছি, সেগুলো হলো- try, catch এবং এগুলো দিয়ে আমাদের যে কোড ব্লকটিতে ইরর হওয়ার সম্ভবনা ছিল, সেই অংগটুকুকে wrap করেছি। এতে করে এই কোড ব্লক-এ যদি কোন ধরণের ইরর হয় তাহলে প্রোগ্রামটি catch ব্লক-এ চলে যায়, এবং এই ব্লক এর ইন্সট্রাকশন গুলো এক্সিকিউট করে এরপর নিচের কোড ব্লক এ চলে যায়।
আর এই প্রক্রিয়াকে আমরা এক্সেপশন হ্যান্ডেলিং বলি, অর্থাৎ প্রোগ্রাম এর কোন অংশে যদি কোন ধরণের এক্সেপশন বা ইরর হয় তাহলে আমাদের প্রোগ্রামটি যাতে বন্ধ না হয় যায় বরং সেইসব অবস্থায় ইউজারকে যাতে করে অর্থপূর্ণ মেসেস দেওয়াকে এক্সেপশন হ্যান্ডেলিং বলে।
The try Block
যদি কোন কোড ব্লক -এ যদি ইরর হওয়ার সম্ভবনা থাকে তাহলে আমরা সেই কেড ব্লক-কে try
ব্লক দিয়ে ইনক্লােজ করতে হয়। উদাহরণ-
এই try
ব্লক এর মাঝে এক বা একাধিক লাইন কোড থাকতে পারে। catch এবং finally ব্লক পরের সেকশনে দেখানো হবে।
একটি উদাহরণ দেখা যাক-
উপরের প্রোগ্রামটিতে একটি মেথড আছে - writeList() যা কিনা একটি ফাইল এ একটি লিস্ট থেকে ভ্যালু পড়ে তা রাইট করে। এই মেথড-টি তে একাধিক এক্সেপশান বা ইরর হতে পারে। যেমন -
out = new PrintWriter(new FileWriter("file.txt"));
এই লাইনটিতে আমরা একটি ফাইল অপেন করার চেষ্টা করেছি। কিন্তু এই ফাইলটি সিস্টেমে নাও থাকতে পারে, কিংবা থাকলেও সেটি অপেন করা যাচ্ছে না ইত্যাদি। সেক্ষেত্রে আমাদরে সিস্টেম IOException
থ্রু করবে এবং প্রোগ্রামটি বন্ধ হয়ে যাবে। এছাড়াও আমরা একটি ফর লুপ ব্যবহার করেছি, এক্ষেত্রে ফাইল এ রাইট করার সময়ও ইরর বা এক্সেপশন হতে পারে। তাই এইসব ইরর বা এক্সেপশন কে হ্যান্ডেল করার জন্যে আমরা কোড ব্লকটিকে try
ব্লক এর ভেতরে রেখেছি। এখন প্রোগ্রামটি চলার সময় যদি কোন ইরর বা একসেপশন হয় তাহলে প্রোগ্রাম এক্সিকিশান সেখান থেকেই catch
ব্লক এ চলে যাবে।
The catch Blocks
try ব্লক এর সাথেই catch ব্লক লিখতে হয়। তবে আমরা একটি try ব্লকের সাথে একাধিক catch ব্লক লিখতে পারি। উদাহরণ-
catch
কিওয়ার্ড এর সাথে প্যারেন্থেসিস এর মাঝে আমরা আর্গুমেন্ট দিতে হয় যা কি টাইপ এক্সেপশন হ্যাল্ডেল করা হচ্ছে তা নির্দেশ করে। এখানে ExceptionType একটি প্লেস হোল্ডার । এখানে যে কোন ক্লাস যা কিনা Throwable ক্লাস কে ইনহেরিট করে তা বসতে পারে।
try ব্লক এর কোন কোড-এ যদি কোন এরর বা এক্সিসেপশন হয় তাহলে প্রেগ্রামের এক্সিকিউশান পয়েন্ট catch
ব্লকে চলে আসে এবং শুধুমাত্র তখনি catch
ব্লক এর কোড এক্সিকিউট হয়।
যদি একাধিক catch
ব্লক থাকে তাহলে এক্সেপশন এর টাইপ অনুযায়ী catch
ব্লক সিলেকটেড হয়।
এখানে try
ব্লকে যদি IndexOutOfBoundsException
হয় তাহলে প্রথম catch
ব্লকটি এক্সিকিউট হবে । আর যদি IOException হয় তাহলে পরের catch
ব্লকটি এক্সিকিউট হবে।
জাভা ৭ এবং পরবর্তি ভার্সন গুলোর জন্যে একটি নতুন ফিচার আছে যাতে করে একটি catch
ব্লক দিয়ে অনেকগুলো এক্সেপশন হ্যান্ডেল করা যায়। উহারহণ -
এখানে catch ক্লজ-এ একাধিক এক্সেপশান একটি ভার্টিকেল বার (|) দিয়ে আলাদা করা হয়।
The finally Block
উপরের উদাহরণ গুলো থেকে দেখলাম যে , try
ব্লক এর কোড -এ এক্সেসেপশন হলে শুধুমাত্র catch
ব্লকের কোড গুলো এক্সিকিউট হয়। তবে আমাদের এমন কোন সিচুয়েশন থাকতে পারে যখন আমরা চাই ইরর হোক বা না হোক, একটি কোড ব্লক আমরা সবসমই এক্সিকিউট করতে চাই , তাহলে আমরা finally ব্যবহার করি।
উপরের প্রোগ্রামটি তে আমরা একটি ফাইল অপেন করছি এবং কিছু কাজ করেছি। এজন্যে একটি FileReader ক্লাসের অবজেক্ট তৈরি করেছি। আমরা চাই এই FileReader অবজেক্টি কাজ শেষ হয়ে গেলে ক্লোজ করতে। এক্ষেত্রে আমরা finally ব্লক এ আমাদের একই ক্লোজিং এর কোডটি লিখেছি। এতে করে এই সুবিধা হচ্ছে যে, আমাদের এই ট্রাই ব্লক-এর কোড কাজ করুক আর না করুক, শেষে আমাদের FileReader এর অবজেক্টটি ক্লোজ হয়ে যাচ্ছে।
অর্থাৎ আমরা শুধুমাত্রে তখনি ফাইনালী ব্লক ব্যবহার করি যখন আমরা নো ম্যাটার হুয়াট, একটি কোড ব্লক সবসময়ই এক্সিকউট করতে চাই।
Identifying Exception Point
try
, catch
এবfinally
ব্লক ব্যাবহার করে এক্সেপশন হ্যান্ডেল করার সময় আমাদের যে বিষয়টির উপর বিশেষ গুরুত্ব দিতে হবে সেটি হল নির্দিষ্ট পয়েন্টেই কেবলtry
এবং catch
ব্যাবহার করা । ঠিক যেখানে এক্সেপশন ঘটবে বা ঘটার সম্ভাবনা থাকবে সেখানেই কেবল আমাদের প্রপার এক্সেপশন হ্যান্ডেলিং থাকা জরুরী । অন্যথায় কোড রান করবে কিন্তু কাঙ্খিত ফলাফল পাওয়া যাবেনা ।
উদাহরন হিসাবে আমরা মনে করি আমাদের একটি মেথড লিখতে বলা হল যেটিতে একটি স্ট্রিং অ্যারে পাস করা হবে এবং সেই অ্যারে এর মাঝ থেকে যে স্ট্রিং গুলা ইন্টিজার নাম্বার রিপ্রেজেন্ট করে সেগুলার যোগফল রিটার্ন করতে হবে । আমরা যদি কোডটি এভাবে লিখিঃ
উপরের কোডটি 21 সংখ্যাটি প্রিন্ট করবে যেটি getSum নামক মেথটি রিটার্ন করছে । কিন্তু আমরা যদি ইনপুট স্ট্রিংটি একটু মডিফাই করে String[] strings = {"1", "2", "3", "four", "5", "6"}; করে দেই তাহলে প্রথমে প্রিন্ট করবে 6 এবং তারপর প্রিন্ট করবে java.lang.NumberFormatException: For input string: "four
। কিন্তু প্রবলেম অনুযায়ী প্রিন্ট করা কথা ছিল 17 । কারন four বাদ দিলে বাকী যতগুলা স্ট্রিং ইন্টিজার নাম্বার রিপ্রেজেন্ট করে সেগুলার যোগফল । সেক্ষেত্রে আমরা যদি কোডটি একটু মডিফাই করে ঠিক যেখানে এক্সেপশন হওয়া সম্ভব সেখানেই try
ব্লকটি ব্যাবহার করতাম তাহলে এই সমস্যা থেকে মুক্তি পাওয়া সম্ভব ছিল । কোডটি যদি এভাবে করিঃ
এবার যদি আমরা String[] strings = {"1", "2", "3", "four", "5", "6"}; এই স্ট্রিংটি ইনপুট আকারে দেই তাহলে দেখবো একটা এক্সেপশন ঠিকই থ্রো করছে তবে রেজাল্ট হিসাবে আমরা যেটি চেয়েছিলাম সেটিও প্রিন্ট করছে । এভাবে আমরা ঠিক নির্দিষ্ট পয়েন্টে এক্সেপশন ডিটেক্ট করে হ্যান্ডেল করতে পারি । এতে করে ওভারঅল কোডের পার্ফরমেন্স যেমন বাড়বে তেমন কোড অনেক বেশি বাগফ্রী ও হবে ।
Checked or Unchecked Exceptions
জাভাতে সব এক্সেপশান গুলো Throwable ক্লাসকে ইনহেরিট করে তৈরি। অর্থাৎ এক্সেপশান হাইআরকি এর একদপ উপরে এই Throwable ক্লাস এর অব্স্থান। এর ঠিক নিচেই দুটি সাব ক্লাস হলে - Exception এবং অন্যটি হলো RuntimeException । এবং এই দুটি ক্লাস দুটি আলাদা শ্রেণীবিভাগের সূচনা করেছে। তবে এই শ্রেণীবিভাগের আরেকটি শাখা আছে, সেটি হলো - Error তবে এগুলো প্রোগ্রাম চলাকালিন সময়ে সাধারণত ধরা হয় না। এগুলো মূলত জাভা রানটাইম সিস্টেম নিজে থেকে হ্যান্ডেল করে এবং এটি আমাদের এই বইয়ের আলোচনার বাইরে।
Last updated