কম্পিউটার প্রোগ্রামিং এ বহুল পরিচিত আর ব্যবহৃত একটা বিষয় হল স্ট্রিং। এক কথায় স্ট্রিং হচ্ছে কতগুলো ক্যারেক্টার এর সিকুয়েন্স বা অনুক্রম।সহজ ভাষায় যখন বেশ কিছু  ক্যারেক্টার একসাথে মিলেমিশে কিছু একটা করার চেষ্টা করে তখন সেটাকে আমরা একটা স্ট্রিং হিসেবে চিন্তা করতেই পারি। প্রোগ্রামিং এ স্ট্রিং এর রয়েছে বিভিন্ন ধরণের ব্যবহার আর নানা ধরণের বৈশিষ্ট্য। তাহলে এখনকার মত পরিচিত হয়ে আসা যাক জাভার স্ট্রিং এর সাথে ।

string

জাভা স্ট্রিং পরিচিতি: 

আমাদের খুব পরিচিত প্রোগ্রামিং ভাষা যেমন সি, সি প্লাস প্লাস এগুলোতে স্ট্রিং কে খুব সহজে ডাটা টাইপ এর ভিতরে ফেলে দেওয়া হলেও জাভা তে স্ট্রিং কে দেখা হয় আস্ত একটা অবজেক্ট হিসেবে।আর সে কারণেই জাভার স্ট্রিং এর সাথে যুক্ত হয়েছে বেশ কিছু বৈশিষ্ট্য ।এই লেখার মাধ্যমে আমরা জাভার স্ট্রিং এর আদ্যোপান্ত নিয়েই ঘাটাঘাটি করার চেষ্টা করব । ওওপি (অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং) এর ধারণা অনুসারে একটা অবজেক্ট অবশ্যই কোন না কোন ক্লাস থেকে তৈরি হয়,জাভাতে স্ট্রিং তৈরি হয় স্ট্রিং ক্লাস থেকে আর এই স্ট্রিং ক্লাসটা রয়েছে java.lang এই প্যাকেজ এর ভিতরে । জাভাতে স্ট্রিং তৈরি করার খুব সহজ দুইটা উপায় আছে, প্রথমটা হল স্ট্রিং লিটারেল এর মাধ্যমে এবং দ্বিতীয়তটি হল new কিওয়ার্ড এবং কন্সট্রাকটর ব্যবহার করে।

public class

এখানে firstString কে তৈরি করা হয়েছে লিটারেল ব্যবহার করে এবং secondString কে তৈরি করা হয়েছে newকিওয়ার্ড এবং কন্সট্রাকটর ব্যবহার করে।আমরা যদি স্ট্রিং তৈরি করা শিখে ফেলি তাহলে আমাদের জন্য পরের ধাপ হবে, যে স্ট্রিং গুলো আমরা তৈরি করব সেগুলোকে জাভা কিভাবে তার মেমোরি তে সংরক্ষণ করে রাখে সেটা জানা । কেননা স্ট্রিং এর জন্য জাভা তার মেমোরি তে বিশেষ একটা জায়গা রেখে দিয়েছে যার নাম হল স্ট্রিং পুল, আর এই বিশেষ জায়গার কাজ অবশ্যই বিশেষ কিছু না হয়ে যায় না।

স্ট্রিং পুল এর ধারনা:

জাভা ভার্চুয়াল মেশিনে মেমোরি মডেল (Memory Model) দুই ভাবে বিভক্ত। একটা হল হিপ এবং অন্যটি হল থ্রেড স্ট্যাক। জাভা প্রোগ্রামে যখন কোন অবজেক্ট তৈরি হয় তখন তাকে জায়গা দেওয়া হয় হিপ এ এবং কোন থ্রেড এক্সিকিউট করার জন্য ব্যাবহার করা হয় থ্রেড স্ট্যাক। তবে আমদের মাথাব্যথা হল হিপ নিয়ে কেননা জাভা হিপের ভিতরে রয়েছে একটা বিশেষ এলাকা যার নাম হল স্ট্রিং পুল (String পুল)। এখন প্রশ্ন হল এই স্ট্রিং পুল কি জিনিস? সহজ কোথায় এ হল স্ট্রিং এর পুকুর অর্থাৎ যে পুকুরে অসংখ্য স্ট্রিং থাকে ।

জাভাতে স্ট্রিং immutable হওয়ার কারনে স্ট্রিং নিয়ে কাজ করার সময় হিপে অনেক নতুন নতুন অবজেক্ট তৈরি হয়ে যায় ।  আর স্ট্রিং অবজেক্ট মেমোরি তে জায়গাও নিয়ে থাকে অনেক বেশি। আবার অনেক সময় এমন ও হয় যে একই  রকম স্ট্রিং অবজেক্ট (স্ট্রিংয়ের ক্যারেক্টারগুলো একই) তৈরি হয়ে যাচ্ছে। এখন যদি একই রকম ক্যারেক্টারের স্ট্রিং এর জন্য বারবার নতুন অবজেক্ট তৈরি না করে একটা অবজেক্ট কে শেয়ার করে ব্যাবহার করা যায় তাহলে যেটা অল্প হলেও বাঁচবে সেটা হল মেমোরি । মেমোরি অপটিমাইজেশন এর চিন্তাভাবনা থেকেই মূলত স্ট্রিং পুল এর জন্ম । আর এটা যে জাভা হিপ এরই একটা অংশ সেটা তো আগেই বলা হয়ে গেছে।

জাভায় যখন লিটারেল ব্যাবহার করে স্ট্রিং তৈরি করা হয় তখন তার জায়গা হয় স্ট্রিং পুল এ। তবে তার আগে জাভা রানটাইম মেশিন (JVM) একটা কাজ করে, সে খুঁজে দেখে যে স্ট্রিং টা তৈরি করার পায়তারা চলছে সেটা স্ট্রিং পুলে আছে কিনা! যদি থাকে তাহলে আর নতুন করে কোন অবজেক্ট তৈরি না করে আগের অবজেক্ট এর একটা রেফারেন্স নতুন স্ট্রিংটা কে দিয়ে দেওয়া হয় । তবে আমরা যদি new কিওয়ার্ড এবং কন্সট্রাকটর ব্যবহার করে স্ট্রিং তৈরি করতে চাই তাহলে সবসময়ই নতুন করে অবজেক্ট তৈরি হবে।

myclass(2)

উপরের উদাহরণ এ firstString এবং secondString এর ভ্যালু একই হওয়ায়  firstString অবজেক্ট এর একটা রেফারেন্স secondString কে দিয়ে দেওয়া হয়েছে, নতুন করে কোন অবজেক্ট তৈরি করা হয় নি। কিন্তু thirdString কে তৈরি করা হচ্ছে new কিওয়ার্ড এবং কন্সট্রাকটর ব্যবহার করে, তাই এ ক্ষেত্রে নতুন একটা অবজেক্ট তৈরি হচ্ছে । এ কারনেই আমরা যখন firstString এবং secondString কে তুলনা করে দেখছি তখন আউটপুট হিসেবে আমরা পাচ্ছি যে তারা দুই জনেই সমান কেননা তারা একই ইন্সটান্স কে রেফার করে আছে। আবার firstString এবং thirdString তুলনা করলে আমরা দেখছি যে তারা সমান না কেননা তারা দুই জনেই ভিন্ন ভিন্ন অবজেক্ট,যদিও তাদের ভ্যালু একই । জাভাতে একটা স্ট্রিং এর সাথে আরেকটা স্ট্রিং কে তুলনা করার জন্যboolean equals(Object another) এবং boolean equalsIgnoreCase(String another) নামে দুইটা মেথড আছে যাদের মধ্যে প্রথম টির কাজ মূলত অবজেক্ট এর ভ্যালু নিয়ে  তুলনা করা এবং দ্বিতীয় টির কাজ হল অন্য একটা স্ট্রিং অবজেক্ট এর ভ্যালু  নিয়ে তুলনা করা । কিন্তু == অপারেটর (operator) তুলনা করে রেফারেন্সের মাধ্যমে, ভ্যালুর মাধ্যমে নয় ।

কম্পিউটার সায়েন্সে String interning নামে একটি টার্ম আছে যা এই স্ট্রিং পুলিং এর কাজ করে দেয়। String interning এর কাজ হল একই ধরনের স্ট্রিংগুলোর শুধু একটাই কপি মেমরিতে থাকবে।

ইমমিউটেবল(Immutable) স্ট্রিং:

জাভাতে স্ট্রিং ক্লাস হল immutable, এর মানে হচ্ছে ,আমি যদি একবার কোন একটা  স্ট্রিং অবজেক্ট তৈরি করে ফেলি তাহলে  তাকে আর পরিবর্তন করতে পারব না। একটু সহজ করে বলতে গেলে, আমরা অনেক ক্লাস লিখি, তারপর এর মাঝে বিভিন্ন ক্লাস ভ্যারিয়েবল রাখি, অবজেক্ট তৈরি করার পর সেই অবজেক্টর এর ভেতরের ভ্যারিয়েবল গুলো বিভিন্ন সময় পরিবতর্তন করতে পারি। কিন্তু স্ট্রিং এর ক্ষেত্রে এটি সম্ভব নয়। অর্থাৎ আমরা যদি কোন একটি ভ্যালু দিয়ে একবার একটি স্ট্রিং অবজেক্ট তৈরি করি তাহলে সেটি আর পরিবর্তন করা যাবে না। নিচের উদাহরণটি ভালভাবে খেয়াল করলে বিষয়টা আমাদের কাছে পরিষ্কার হয়ে যাবে আশা করি।

first strings

এখানে concat() এই মেথড টার কাজ হল একটা স্ট্রিং এর শেষে আরেকটি স্ট্রিংকে জুড়ে দেওয়া ।কাজেই আমাদের কাছে যদিও মনে হচ্ছে যে firstString অবজেক্টটির ভ্যালু বদলে গেছে, কিন্তু আসলে যেটা হয়েছে সেটা হল “ShadmanSakib” এই  ভ্যালু  নিয়ে নতুন একটা অবজেক্ট তৈরি হয়েছে । কিন্তু firstString  এখনো রেফার করে আছে “Shadman” কেই এবং নতুন তৈরি হওয়া অবজেক্ট টির কোন রেফারেন্স ভ্যারিয়েবল না থাকার কারনে আমরা যখন firstString কে প্রিন্ট করে দেখছি তখন আমরা ভ্যালু পাচ্ছি “Shadman” । তার মানে firstString এর কোন পরিবর্তন হয়নি । এখন কোডটা একটু বদলে দিলাম ।

এবার যদিও মনে হচ্ছে আমরা স্ট্রিং এর ভ্যালু পরিবর্তন করে ফেলতে পেরেছি, কিন্তু আসলে এবারও সেটা হয় নি। এখানে firstString অবজেক্ট এর ভ্যালুর সাথে নতুন ভ্যালু যোগ করে একেবারে নতুন একটা অবজেক্ট তৈরি হচ্ছে এবং firstString এখন রেফার করবে এই নতুন অবজেক্ট টিকে । তাহলে আগের অবজেক্টটির কি হবে? জাভার  গার্বেজ কালেক্টর এই রেফারেন্স বিহীন অবজেক্টটি কে মেমোরি থেকে সরিয়ে ফেলবে। এখন প্রশ্ন হচ্ছে “Shadman” এই  ভ্যালুটির কোন পরিবর্তন কি আমরা করতে পেরেছি? উত্তর হল না, কেননা Immutable হওয়ার কারণে ভ্যালু পরিবর্তন করতে গেলে নতুন ভ্যালু নিয়ে নতুন আরেকটি অবজেক্ট তৈরি হচ্ছে ।

 ইমমিউটেবল(Immutable) স্ট্রিং কেন দরকার??

স্ট্রিং পুল থেকে যদি একই ভ্যালু হয় তাহলে নতুন অবজেক্ট তৈরি না করে রেফারেন্স দিয়ে দেওয়া হয় যেটা আমরা আগেই দেখে ফেলছি। এখন যদি স্ট্রিং Immutable না হত তাহলে কোন একটা স্ট্রিং যদি পরিবর্তন করা হয় তাহলে অন্যান্য রেফারেন্স গুলোর ও পরিবর্তন হয়ে যাবে, যেটা কখনোই কাম্য নয়।

বিভিন্ন নেটওয়ার্ক কানেকশন, ডাটাবেজ কানেকশন ইউ আর এল (URL) , ইউজারনেম পাসওয়ার্ড ইত্যাদি ক্ষেত্রে প্যারামিটার হিসেবে স্ট্রিং ব্যবহার করা হয়। সুতরাং স্ট্রিং immutable না হলে পরিবর্তন করে ফেলা সম্ভব,  যা কিনা একটি সিরিয়াস রকম সিকিউরিটি থ্রেড হতে পারে।

ক্লাস লোডিং এর ক্ষেত্রে স্ট্রিং কে আর্গুমেন্ট হিসেবে ব্যবহার করা হয়। স্ট্রিং যদি Immutable না হত থলে ভুল ক্লাস লোড হয়ে যাওয়ার একটা সম্ভাবনা থেকে যেত। এছাড়া স্ট্রিং Immutable হওয়ার কারণে এটা থ্রেড সেফ এবং স্বাধীনভাবে থ্রেড একসেস করতে পারে। যার ফলে থ্রেড synchronization এবং থ্রেড সেফটি  নিয়ে আমাদের চিন্তা করতে হয় না।

শেষ কথা:

জাভা স্ট্রিংয়ের বিভিন্ন ধরনের অপারেশন করার জন্য আমাদের অনেক গুলো মেথড তৈরি করে দিয়েছে। যেমন স্ট্রিং এর দৈর্ঘ্য বের করার জন্য length(), বড় হাতের অক্ষরে পরিবর্তন করার জন্য toUpperCase(), ছোট হাতের অক্ষরে পরিবর্তন করার জন্য toLowerCase() ইত্যাদি আরো অনেক। এখন একটা শেষ প্রশ্ন , জাভা স্ট্রিং ক্লাস Immutable,কিন্তু আমাদের যদি mutable স্ট্রিং এর দরকার হয় তাহলে উপায় কি ? জাভা  আমাদের StringBuffer আর StringBuilder নামক দুইটি ক্লাস দিয়েছে যাদের মাধ্যমে mutable স্ট্রিং তৈরি করা সম্ভব।

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *