1. বাহ্যিক সম্পদ
যেহেতু একটি জাভা প্রোগ্রাম চলে, কখনও কখনও এটি জাভা মেশিনের বাইরে সত্তার সাথে যোগাযোগ করে। উদাহরণস্বরূপ, ডিস্কে ফাইল সহ। এই সত্ত্বা সাধারণত বহিরাগত সম্পদ বলা হয়. অভ্যন্তরীণ সম্পদ হল জাভা মেশিনের ভিতরে তৈরি বস্তু।
সাধারণত, মিথস্ক্রিয়া এই স্কিম অনুসরণ করে:
ট্র্যাকিং সম্পদ
অপারেটিং সিস্টেম কঠোরভাবে উপলব্ধ সংস্থানগুলির ট্র্যাক রাখে এবং বিভিন্ন প্রোগ্রাম থেকে তাদের শেয়ার করা অ্যাক্সেস নিয়ন্ত্রণ করে। উদাহরণস্বরূপ, যদি একটি প্রোগ্রাম একটি ফাইল পরিবর্তন করে, তবে অন্য একটি প্রোগ্রাম সেই ফাইলটি পরিবর্তন (বা মুছে) করতে পারে না। এই নীতিটি ফাইলগুলিতে সীমাবদ্ধ নয়, তবে তারা সবচেয়ে সহজে বোধগম্য উদাহরণ প্রদান করে।
অপারেটিং সিস্টেমের ফাংশন (APIs) রয়েছে যা একটি প্রোগ্রামকে সম্পদ অর্জন এবং/অথবা প্রকাশ করতে দেয়। যদি কোনও সংস্থান ব্যস্ত থাকে, তবে কেবলমাত্র সেই প্রোগ্রামটি যা অর্জিত হয়েছে তার সাথে কাজ করতে পারে। যদি একটি সম্পদ বিনামূল্যে হয়, তাহলে যেকোনো প্রোগ্রাম এটি অর্জন করতে পারে।
কল্পনা করুন যে আপনার অফিসে কফির মগ শেয়ার করা হয়েছে। কেউ যদি একটি মগ নেয়, তবে অন্য লোকেরা তা নিতে পারে না। কিন্তু মগ একবার ব্যবহার করে, ধুয়ে তার জায়গায় রেখে দিলে যে কেউ আবার নিতে পারবে। বাস বা সাবওয়েতে আসনগুলির অবস্থা একই। একটা সিট ফ্রি থাকলে যে কেউ নিতে পারবে। যদি একটি আসন দখল করা হয়, তবে এটি যে ব্যক্তি নিয়েছে তার দ্বারা নিয়ন্ত্রিত হয়।
বাহ্যিক সম্পদ অর্জন ।
প্রতিবার আপনার জাভা প্রোগ্রামটি ডিস্কের একটি ফাইলের সাথে কাজ শুরু করে, জাভা মেশিন অপারেটিং সিস্টেমকে এটিতে একচেটিয়া অ্যাক্সেসের জন্য জিজ্ঞাসা করে। যদি সম্পদ বিনামূল্যে হয়, তাহলে জাভা মেশিন এটি অর্জন করে।
কিন্তু আপনি ফাইলটির সাথে কাজ শেষ করার পরে, এই সংস্থানটি (ফাইল) অবশ্যই প্রকাশ করতে হবে, অর্থাৎ আপনাকে অপারেটিং সিস্টেমকে অবহিত করতে হবে যে আপনার আর এটির প্রয়োজন নেই। যদি আপনি এটি না করেন, তাহলে সম্পদ আপনার প্রোগ্রাম দ্বারা অনুষ্ঠিত হতে থাকবে।
অপারেটিং সিস্টেম প্রতিটি চলমান প্রোগ্রাম দ্বারা দখলকৃত সম্পদের একটি তালিকা বজায় রাখে। যদি আপনার প্রোগ্রাম নির্ধারিত রিসোর্স সীমা অতিক্রম করে, তাহলে অপারেটিং সিস্টেম আপনাকে আর নতুন রিসোর্স দেবে না।
ভাল খবর হল যে আপনার প্রোগ্রামটি বন্ধ হয়ে গেলে, সমস্ত সংস্থান স্বয়ংক্রিয়ভাবে প্রকাশিত হয় (অপারেটিং সিস্টেম নিজেই এটি করে)।
খারাপ খবর হল যে আপনি যদি একটি সার্ভার অ্যাপ্লিকেশন লিখছেন (এবং প্রচুর সার্ভার অ্যাপ্লিকেশন জাভাতে লেখা হয়), আপনার সার্ভারটি বন্ধ না করে দিন, সপ্তাহ এবং মাস চালানোর জন্য সক্ষম হতে হবে। এবং যদি আপনি দিনে 100টি ফাইল খোলেন এবং সেগুলি বন্ধ না করেন, তবে কয়েক সপ্তাহের মধ্যে আপনার অ্যাপ্লিকেশনটি তার সংস্থান সীমায় পৌঁছে যাবে এবং ক্র্যাশ হয়ে যাবে। এটি স্থিতিশীল কাজের মাসের তুলনায় অনেক কম পড়ছে।
2. close()
পদ্ধতি
যে ক্লাসগুলি বাহ্যিক সংস্থানগুলি ব্যবহার করে তাদের মুক্তির জন্য একটি বিশেষ পদ্ধতি রয়েছে close()
:
নীচে আমরা একটি প্রোগ্রামের একটি উদাহরণ প্রদান করি যা একটি ফাইলে কিছু লেখে এবং তারপর ফাইলটি শেষ হয়ে গেলে বন্ধ করে দেয়, অর্থাৎ এটি অপারেটিং সিস্টেমের সংস্থানগুলিকে মুক্ত করে। এটা এই মত কিছু দেখায়:
কোড | বিঃদ্রঃ |
---|---|
|
ফাইলের পথ। ফাইল অবজেক্ট পান: সম্পদ অর্জন করুন। ফাইলটিতে লিখুন ফাইলটি বন্ধ করুন - সংস্থানটি ছেড়ে দিন |
একটি ফাইল (বা অন্যান্য বাহ্যিক সংস্থান) এর সাথে কাজ করার পরে, আপনাকে close()
বহিরাগত সংস্থানের সাথে লিঙ্কযুক্ত বস্তুর পদ্ধতিটি কল করতে হবে।
ব্যতিক্রম
এটা সব সহজ মনে হয়. কিন্তু প্রোগ্রাম চলার সাথে সাথে ব্যতিক্রম ঘটতে পারে এবং বাহ্যিক সংস্থান প্রকাশ করা হবে না। আর সেটা খুবই খারাপ।
পদ্ধতিটি সর্বদা কল করা হয় তা নিশ্চিত করার জন্য close()
, আমাদের কোডটি একটি try
- catch
- finally
ব্লকে মোড়ানো এবং close()
ব্লকে পদ্ধতিটি যুক্ত করতে হবে finally
। এটি এই মত কিছু দেখাবে:
try
{
FileOutputStream output = new FileOutputStream(path);
output.write(1);
output.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
output.close();
}
এই কোডটি কম্পাইল করবে না, কারণ output
ভেরিয়েবলটি ব্লকের ভিতরে ঘোষণা করা হয়েছে try {}
এবং তাই ব্লকে দৃশ্যমান নয় finally
।
আসুন এটি ঠিক করা যাক:
FileOutputStream output = new FileOutputStream(path);
try
{
output.write(1);
output.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
output.close();
}
এটা ঠিক আছে, কিন্তু এটা কাজ করবে না যদি আমরা FileOutputStream
অবজেক্ট তৈরি করার সময় কোনো ত্রুটি দেখা দেয় এবং এটি খুব সহজেই ঘটতে পারে।
আসুন এটি ঠিক করা যাক:
FileOutputStream output = null;
try
{
output = new FileOutputStream(path);
output.write(1);
output.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
output.close();
}
এখনও কিছু সমালোচনা আছে। প্রথমত, যদি অবজেক্ট তৈরি করার সময় একটি ত্রুটি ঘটে FileOutputStream
, তাহলে output
ভেরিয়েবলটি নাল হবে। এই সম্ভাবনা ব্লকের জন্য অ্যাকাউন্ট করা আবশ্যক finally
.
দ্বিতীয়ত, close()
পদ্ধতিটি সর্বদা ব্লকে বলা হয় finally
, যার অর্থ ব্লকে এটি প্রয়োজনীয় নয় try
। চূড়ান্ত কোড এই মত দেখাবে:
FileOutputStream output = null;
try
{
output = new FileOutputStream(path);
output.write(1);
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (output != null)
output.close();
}
এমনকি যদি আমরা ব্লকটি বিবেচনা না করি catch
, যা বাদ দেওয়া যেতে পারে, তাহলে আমাদের কোডের 3 লাইন 10 হয়ে যায়। কিন্তু আমরা মূলত ফাইলটি খুলেছিলাম এবং 1 লিখেছিলাম। একটু কষ্টকর, আপনি কি মনে করেন না?
3. try
সম্পদ সহ
এবং এখানে জাভার নির্মাতারা আমাদের উপর কিছু সিনট্যাকটিক চিনি ছিটিয়ে দেওয়ার সিদ্ধান্ত নিয়েছে। এর 7 তম সংস্করণ দিয়ে শুরু করে, জাভা একটি নতুন try
-সম্পদের সাথে বিবৃতি দিয়েছে।
এটি পদ্ধতিতে বাধ্যতামূলক কল দিয়ে সমস্যার সমাধান করার জন্য অবিকল তৈরি করা হয়েছিল close()
। সাধারণ ক্ষেত্রে বেশ সহজ দেখায়:
try (ClassName name = new ClassName())
{
Code that works with the name variable
}
এটি বিবৃতির আরেকটি try
ভিন্নতা । আপনাকে try
কীওয়ার্ডের পরে বন্ধনী যোগ করতে হবে, এবং তারপর বন্ধনীর ভিতরে বাহ্যিক সংস্থান সহ বস্তু তৈরি করতে হবে। বন্ধনীর প্রতিটি বস্তুর জন্য, কম্পাইলার finally
পদ্ধতিতে একটি বিভাগ এবং একটি কল যোগ করে close()
।
নীচে দুটি সমতুল্য উদাহরণ রয়েছে:
দীর্ঘ কোড | সম্পদের সাথে চেষ্টা করে দেখুন |
---|---|
|
|
-সহ-সম্পদ ব্যবহার করে কোডটি try
অনেক ছোট এবং পড়া সহজ। এবং আমাদের কাছে যত কম কোড থাকবে, টাইপো বা অন্য ত্রুটি হওয়ার সম্ভাবনা তত কম।
যাইহোক, আমরা -with-resources স্টেটমেন্টে যোগ catch
এবং finally
ব্লক করতে পারি। try
অথবা প্রয়োজন না হলে আপনি তাদের যোগ করতে পারবেন না।
4. একই সময়ে বেশ কয়েকটি ভেরিয়েবল
যাইহোক, আপনি প্রায়ই এমন পরিস্থিতির সম্মুখীন হতে পারেন যখন আপনাকে একই সময়ে একাধিক ফাইল খুলতে হবে। ধরা যাক আপনি একটি ফাইল অনুলিপি করছেন, তাই আপনার দুটি বস্তুর প্রয়োজন: যে ফাইল থেকে আপনি ডেটা অনুলিপি করছেন এবং যে ফাইলটিতে আপনি ডেটা অনুলিপি করছেন।
এই ক্ষেত্রে, try
-with-resources স্টেটমেন্ট আপনাকে এটিতে একটি কিন্তু বেশ কয়েকটি অবজেক্ট তৈরি করতে দেয়। অবজেক্ট তৈরি করে এমন কোড সেমিকোলন দ্বারা আলাদা করা আবশ্যক। এখানে এই বিবৃতিটির সাধারণ চেহারা:
try (ClassName name = new ClassName(); ClassName2 name2 = new ClassName2())
{
Code that works with the name and name2 variables
}
ফাইল কপি করার উদাহরণ:
দীর্ঘ কোড | শর্ট কোড |
---|---|
|
|
আচ্ছা, আমরা এখানে কি বলতে পারি? try
সম্পদ সহ একটি বিস্ময়কর জিনিস!
5. AutoCloseable
ইন্টারফেস
কিন্তু এখানেই শেষ নয়. মনোযোগী পাঠক অবিলম্বে এই বিবৃতিটি কীভাবে প্রয়োগ করা যেতে পারে তা সীমাবদ্ধ করে এমন ত্রুটিগুলি সন্ধান করতে শুরু করবে।
কিন্তু কিভাবে try
-with-resources স্টেটমেন্ট কাজ করে যদি ক্লাসের কোন close()
পদ্ধতি না থাকে? ঠিক আছে, ধরুন যে কিছুই বলা হবে না। কোন পদ্ধতি নেই, কোন সমস্যা নেই।
কিন্তু কিভাবে try
-সহ-সম্পদ বিবৃতি কাজ করে যদি ক্লাসের বিভিন্ন close()
পদ্ধতি থাকে? আর তাদের কাছে যুক্তির কি দরকার? close()
এবং ক্লাসের পরামিতি ছাড়া একটি পদ্ধতি নেই ?
আমি আশা করি আপনি সত্যিই নিজেকে এই প্রশ্ন জিজ্ঞাসা করেছেন, এবং সম্ভবত এখনও অন্যদের.
এই ধরনের সমস্যাগুলি এড়াতে, জাভা-এর নির্মাতারা একটি বিশেষ ইন্টারফেস নিয়ে এসেছেন AutoCloseable
, যার একটি মাত্র পদ্ধতি রয়েছে — close()
যার কোনো প্যারামিটার নেই।
তারা এই বিধিনিষেধটিও যোগ করেছে যে কেবলমাত্র ক্লাসের অবজেক্টগুলি যেগুলি বাস্তবায়ন করে তাদেরAutoCloseable
সম্পদ হিসাবে ঘোষণা করা যেতে পারে try
--সহ-সম্পদ বিবৃতিতে। ফলস্বরূপ, এই ধরনের বস্তুর সর্বদা close()
কোন পরামিতি ছাড়া একটি পদ্ধতি থাকবে।
যাইহোক, আপনি কি মনে করেন যে একটি try
-with-resources স্টেটমেন্টের পক্ষে রিসোর্স হিসাবে এমন একটি অবজেক্ট ঘোষণা করা সম্ভব যার ক্লাসের close()
প্যারামিটার ছাড়া নিজস্ব পদ্ধতি রয়েছে কিন্তু যা বাস্তবায়ন করে না AutoCloseable
?
খারাপ খবর: সঠিক উত্তর হল না — ক্লাসগুলিকে অবশ্যই AutoCloseable
ইন্টারফেস প্রয়োগ করতে হবে।
সুসংবাদ: জাভাতে অনেকগুলি ক্লাস রয়েছে যা এই ইন্টারফেসটি বাস্তবায়ন করে, তাই এটি খুব সম্ভব যে সবকিছুই এটির মতো কাজ করবে।
GO TO FULL VERSION