কম্পিউটার টিউটোরিয়াল

জাভা জেনেরিকস মাস্টার করুন: স 명확 গাইড - এগুলো কী এবং কীভাবে ব্যবহার করবেন

জাভা জেনেরিকস জাভা ল্যাঙ্গুয়েজের সবচেয়ে গুরুত্বপূর্ণ বৈশিষ্ট্যগুলোর একটি। জেনেরিকসের পেছনে আইডিয়া খুব সিম্পল, কিন্তু এর সাথে জড়িত সাধারণ সিনট্যাক্স থেকে শিফ্ট হওয়ার কারণে এটি কখনও কখনও জটিল মনে হয়।

এই টিউটোরিয়ালের উদ্দেশ্য হল আপনাকে জেনেরিকসের এই উপযোগী কনসেপ্টটি সহজে বোঝানো।

তবে জেনেরিকসের ভিতরে ঢুকার আগে, আসুন বুঝি জাভা জেনেরিকস প্রথমে কেন দরকার ছিল।

জাভা জেনেরিকসের উদ্দেশ্য

Java 5-এ জেনেরিকস চালু হওয়ার আগে, আপনি নিচের কোড স্নিপেটটি কম্পাইল করতে পারতেন কোনো এরর বা ওয়ার্নিং ছাড়া:

List list = new ArrayList();
list.add("hey");
list.add(new Object());

আপনি কোনো লিস্ট বা অন্য জাভা কালেকশনে ডেটা টাইপ ডিক্লেয়ার না করেই যেকোনো টাইপের ভ্যালু যোগ করতে পারতেন। কিন্তু যখন আপনি লিস্ট থেকে ভ্যালু রিট্রিভ করতেন, তখন আপনাকে এক্সপ্লিসিটলি সেটি একটি নির্দিষ্ট টাইপে কাস্ট করতে হতো।

উপরের লিস্টটি ইটারেট করার কথা চিন্তা করুন।

for (int i = 0; i < list.size(); i++) {
    String value = (String) list.get(i); // i=1 হলে ClassCastException
}

স্টোর করা ডেটা টাইপ ডিক্লেয়ার না করেই লিস্ট তৈরি করার অনুমতি দেওয়া, উপরের মত প্রোগ্রামারদের ভুলের কারণ হতে পারে যা রানটাইমে ClassCastExceptions থ্রো করে।

জেনেরিকস চালু করা হয়েছিল প্রোগ্রামারদের এই ধরনের ভুল থেকে বাঁচাতে।

জেনেরিকস দিয়ে, আপনি জাভা কালেকশন তৈরি করার সময় স্টোর করা ডেটা টাইপ এক্সপ্লিসিটলি ডিক্লেয়ার করতে পারেন নিচের উদাহরণটি দেখায়।

নোট: আপনি এখনও স্টোর করা ডেটা টাইপ স্পেসিফাই না করেই জাভা কালেকশন অবজেক্ট তৈরি করতে পারেন কিন্তু এটা রিকমেন্ডেড নয়।

List stringList = new ArrayList<>();

এখন, আপনি কম্পাইল-টাইম এরর পাওয়া ছাড়া একটি String টাইপের লিস্টে Integer ভুলবশত স্টোর করতে পারবেন না। এটি নিশ্চিত করে যে আপনার প্রোগ্রাম রানটাইম এররে পড়বে না।

stringList.add(new Integer(4)); // কম্পাইল টাইম এরর

জাভায় জেনেরিকস চালু করার মূল উদ্দেশ্য ছিল রানটাইমে ClassCastExceptions-এ পড়া এড়ানো।

জাভা জেনেরিকস তৈরি করা

আপনি জেনেরিকস ব্যবহার করে জাভা ক্লাস এবং মেথড তৈরি করতে পারেন। আসুন প্রতিটি টাইপের জেনেরিকস কীভাবে তৈরি করা যায় সেটি দেখি।

জেনেরিক ক্লাস

একটি জেনেরিক ক্লাস তৈরি করার সময়, ক্লাসের জন্য টাইপ প্যারামিটার ক্লাসের নামের শেষে অ্যংল <> ব্র্যাকেটের ভিতরে যোগ করা হয়।

public class GenericClass {
    private T item;

    public void setItem(T item) {
        this.item = item;
    }

    public T getItem() {
        return this.item;
    }
}

এখানে, T হল ডেটা টাইপ প্যারামিটার। জাভা কনভেনশন অনুযায়ী T, N, এবং E ডেটা টাইপ প্যারামিটার için ব্যবহৃত কিছু লেটার।

উপরের উদাহরণে, আপনি একটি GenericClass অবজেক্ট তৈরি করার সময় একটি স্পেসিফিক ডেটা টাইপ পাস করতে পারেন।

public static void main(String[] args) {
    GenericClass gc1 = new GenericClass<>();
    gc1.setItem("hello");
    String item1 = gc1.getItem(); // "hello"
    gc1.setItem(new Object()); // Error

    GenericClass gc2 = new GenericClass<>();
    gc2.setItem(new Integer(1));
    Integer item2 = gc2.getItem(); // 1
    gc2.setItem("hello"); // Error
}

আপনি জেনেরিক ক্লাস অবজেক্ট তৈরি করার সময় ডেটা টাইপ প্যারামিটারে প্রিমিটিভ ডেটা টাইপ পাস করতে পারবেন না। শুধু Object টাইপ এক্সটেন্ড করা ডেটা টাইপগুলোই টাইপ প্যারামিটার হিসেবে পাস করা যায়।

উদাহরণস্বরূপ:

GenericClass gc3 = new GenericClass<>(); // Error

জেনেরিক মেথড

জেনেরিক মেথড তৈরি করা জেনেরিক ক্লাস তৈরির মতো একই প্যাটার্ন ফলো করে। আপনি একটি জেনেরিক ক্লাসের ভিতরে এবং একটি নন-জেনেরিক ক্লাসের ভিতরেও জেনেরিক মেথড ইমপ্লিমেন্ট করতে পারেন।

public class GenericMethodClass {
    public static  void printItems(T[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }

    public static void main(String[] args) {
        String[] arr1 = {"Cat", "Dog", "Mouse"};
        Integer[] arr2 = {1, 2, 3};
        GenericMethodClass.printItems(arr1); // "Cat", "Dog", "Mouse"
        GenericMethodClass.printItems(arr2); // 1, 2, 3
    }
}

এখানে, আপনি একটি নির্দিষ্ট টাইপের অ্যারে পাস করে মেথডটি প্যারামিটারাইজ করতে পারেন। জেনেরিক মেথড printItems() পাস করা অ্যারে জানতে ইটারেট করে এবং আইটেমগুলো প্রিন্ট করে ঠিক একটি নরমাল জাভা মেথডের মতো।

বাউন্ডেড টাইপ প্যারামিটার

আমরা 여태껏 যে জেনেরিক ক্লাস এবং মেথডগুলো তৈরি করেছি সেগুলো প্রিমিটিভ টাইপ ছাড়া যেকোনো ডেটা টাইপে প্যারামিটারাইজ করা যায়। কিন্তু যদি আমরা জেনেরিক্সে পাস করা ডেটা টাইপগুলো লিমিট করতে চাই? এখানেই বাউন্ডেড টাইপ প্যারামিটার কাজে আসে।

আপনি একটি জেনেরিক ক্লাস বা মেথড দিয়ে এক্সেপ্ট করা ডেটা টাইপগুলো বাউন্ড করতে পারেন স্পেসিফাই করে যে সেটি অবশ্যই অন্য একটি ডেটা টাইপের সাবক্লাস হতে হবে।

উদাহরণস্বরূপ:

// শুধু List-এর সাবক্লাস এক্সেপ্ট করে
public class UpperBoundedClass {
    // শুধু List-এর সাবক্লাস এক্সেপ্ট করে
    public  void UpperBoundedMethod(T[] arr) { }
}

এখানে, UpperBoundedClass এবং UpperBoundedMethod শুধু List ডেটা টাইপের সাবটাইপ ব্যবহার করে প্যারামিটারাইজ করা যাবে।

List ডেটা টাইপ টাইপ প্যারামিটারের জন্য একটি আপার বাউন্ড হিসেবে কাজ করে। যদি আপনি List এর সাবটাইপ নয় এমন একটি ডেটা টাইপ ব্যবহার করার চেষ্টা করেন, তবে কম্পাইল-টাইম এরর থ্রো হবে।

বাউন্ডগুলো শুধু ক্লাসগুলোতে সীমাবদ্ধ নয়। আপনি ইন্টারফেসও পাস করতে পারেন। ইন্টারফেস এক্সটেন্ড করা মানে এই কেসে, ইন্টারফেস ইমপ্লিমেন্ট করা।

একটি প্যারামিটারের একাধিক বাউন্ডও হতে পারে এই উদাহরণে দেখানো হয়েছে।

// Mammal এবং Animal উভয়ের সাবক্লাস এক্সেপ্ট করে
public class MultipleBoundedClass {
    // Mammal এবং Animal উভয়ের সাবক্লাস এক্সেপ্ট করে
    public  void MultipleBoundedMethod(T[] arr) { }
}

এক্সেপ্ট করা ডেটা টাইপ অবশ্যই Animal এবং Mammal ক্লাস দুটির সাবক্লাস হতে হবে। যদি এই বাউন্ডগুলোর একটি ক্লাস হয়, তবে সেটি বাউন্ড ডিক্লেরেশনে প্রথমে আসতে হবে।

উপরের উদাহরণে, যদি Mammal একটি ক্লাস এবং Animal একটি ইন্টারফেস হয়, তবে উপরে দেখানো মত Mammal প্রথমে আসতে হবে। অন্যথায়, কোড কম্পাইল-টাইম এরর থ্রো করবে।

জাভা জেনেরিকস ওয়াইল্ডকার্ড

ওয়াইল্ডকার্ডগুলো জেনেরিক টাইপের প্যারামিটার মেথডগুলোর কাছে পাস করতে ব্যবহৃত হয়। একটি জেনেরিক মেথডের বিপরীতে, এখানে জেনেরিক প্যারামিটারটি মেথড tarafından এক্সেপ্ট করা প্যারামিটারগুলোর কাছে পাস করা হয়, যা উপরে আলোচনা করা ডেটা টাইপ প্যারামিটার থেকে আলাদা। একটি ওয়াইল্ডকার্ড ? সিম্বল দিয়ে রিপ্রেজেন্ট করা হয়।

public void printItems(List list) {
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
    }
}

উপরের printItems() মেথডটি যেকোনো ডেটা টাইপের লিস্ট প্যারামিটার হিসেবে এক্সেপ্ট করে। এটি প্রোগ্রামারদের ভিন্ন ডেটা টাইপের লিস্টের জন্য কোড রিপিট করতে হয় না, যা জেনেরিকস ছাড়া হতো।

আপার বাউন্ডেড ওয়াইল্ডকার্ড

যদি আমরা মেথড দ্বারা এক্সেপ্ট করা লিস্টে স্টোর করা ডেটা টাইপগুলো লিমিট করতে চাই, তবে আমরা বাউন্ডেড ওয়াইল্ডকার্ড ব্যবহার করতে পারি।

উদাহরণ:

public void printSubTypes(List list) {
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
    }
}

printSubTypes() মেথডটি শুধু সেই লিস্টগুলো এক্সেপ্ট করে যেগুলো Color-এর সাবটাইপ স্টোর করে। এটি RedColor বা BlueColor অবজেক্টের লিস্ট এক্সেপ্ট করবে, কিন্তু Animal অবজেক্টের লিস্ট এক্সেপ্ট করবে না। কারণ Animal Color-এর সাবটাইপ নয়। এটি একটি আপার-বাউন্ডেড ওয়াইল্ডকার্ডের উদাহরণ।

লোয়ার বাউন্ডেড ওয়াইল্ডকার্ড

একইভাবে, যদি আমাদের ছিল:

public void printSuperTypes(List list) {
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
    }
}

তাহলে, printSuperTypes() মেথডটি শুধু সেই লিস্টগুলো এক্সেপ্ট করবে যেগুলো Dog ক্লাসের সুপার টাইপ স্টোর করে। এটি Mammal বা Animal অবজেক্টের লিস্ট এক্সেপ্ট করবে কিন্তু LabDog অবজেক্টের লিস্ট এক্সেপ্ট করবে না কারণ LabDog Dog-এর সুপারক্লাস নয়, বরং সাবক্লাস। এটি একটি লোয়ার-বাউন্ডেড ওয়াইল্ডকার্ডের উদাহরণ।

উপসংহার

জাভা জেনেরিকস তার চালু হওয়ার পর থেকে প্রোগ্রামারদের জন্য একটি অনিবার্য ফিচার बन चुका।

এই জনপ্রিয়তার কারণ হল প্রোগ্রামারদের জীবন সহজ করার এর ইম্প্যাক্ট। কোডিং ভুল থেকে বাঁচানোর পাশাপাশি, জেনেরিকসের ব্যবহার কোড কম রিপিটেটিভ করে। কি আপনি লক্ষ্য করেছেন কীভাবে এটি ক্লাস এবং মেথডকে জেনারেলাইজ করে ভিন্ন ডেটা টাইপের জন্য কোড রিপিট করার প্রয়োজন নেই?

জেনেরিকসের ভালো ধারণা থাকা ল্যাঙ্গুয়েজে এক্সপার্ট হওয়ার জন্য গুরুত্বপূর্ণ। তাই, এই টিউটোরিয়ালে শিখা জিনিসগুলো প্র্যাকটিক্যাল কোডে প্রয়োগ করা এগিয়ে যাওয়ার পথ।

  1. DNS লিক কী এবং কীভাবে সেটি ফিক্স করবেন

  2. Google Maps Plus Codes আবিষ্কার করুন: বিশ্বের যেকোনো জায়গা খুঁজে বের করার সহজ গাইড

  3. গুগল অ্যাসিস্ট্যান্ট রুটিন মাস্টার করুন: দ্রুত সেট আপ করার গাইড

  4. সিস্টেম ইন্টারনালস: উইন্ডোজ প্রশাসনের জন্য শক্তিশালী টুলস