CodeGym /Java Blog /এলোমেলো /জাভাতে জেনেরিক
John Squirrels
লেভেল 41
San Francisco

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

এলোমেলো দলে প্রকাশিত
ওহে! আমরা জাভা জেনেরিক সম্পর্কে কথা বলতে যাচ্ছি। আমি বলব যে আপনি অনেক কিছু শিখবেন! শুধু এই পাঠ নয়, পরবর্তী কয়েকটি পাঠও জেনেরিকের প্রতি নিবেদিত হবে। সুতরাং, আপনি যদি জেনেরিক্সে আগ্রহী হন তবে আজকের দিনটি আপনার ভাগ্যবান: আপনি জেনেরিকের বৈশিষ্ট্যগুলি সম্পর্কে অনেক কিছু শিখবেন। আর না হলে নিজেই পদত্যাগ করুন আর শিথিল করুন! :) এটি একটি অত্যন্ত গুরুত্বপূর্ণ বিষয়, এবং আপনাকে এটি জানতে হবে। আসুন সহজ দিয়ে শুরু করি: "কি" এবং "কেন"।

জাভা জেনেরিক কি?

জেনেরিক্স হল এমন প্রকার যার একটি প্যারামিটার আছে। একটি জেনেরিক টাইপ তৈরি করার সময়, আপনি শুধুমাত্র একটি টাইপ নয়, এটি যে ডেটা টাইপ দিয়ে কাজ করবে তাও উল্লেখ করুন। আমি অনুমান করছি সবচেয়ে সুস্পষ্ট উদাহরণ ইতিমধ্যে আপনার মনে এসেছে: ArrayList! এইভাবে আমরা সাধারণত একটি প্রোগ্রামে একটি তৈরি করি:

import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<String> myList1 = new ArrayList<>();
       myList1.add("Test String 1");
       myList1.add("Test String 2");
   }
}
আপনি অনুমান করতে পারেন, এই তালিকার একটি বৈশিষ্ট্য হল যে আমরা এটিতে সবকিছু স্টাফ করতে পারি না: এটি স্ট্রিং অবজেক্টের সাথে একচেটিয়াভাবে কাজ করে। এখন জাভার ইতিহাসে একটু ডিগ্রেশন করা যাক এবং "কেন?" প্রশ্নের উত্তর দেওয়ার চেষ্টা করি। এটি করার জন্য, আমরা ArrayList ক্লাসের আমাদের নিজস্ব সরলীকৃত সংস্করণ লিখব। আমাদের তালিকা শুধুমাত্র জানে কিভাবে একটি অভ্যন্তরীণ অ্যারে থেকে ডেটা যোগ করতে এবং পুনরুদ্ধার করতে হয়:

public class MyListClass {

   private Object[] data;
   private int count;

   public MyListClass() {
       this.data = new Object[10];
       this.count = 0;
   }

   public void add(Object o) {
       this.data[count] = o;
       count++;
   }

   public Object[] getData() {
       return data;
   }
}
ধরুন আমরা আমাদের তালিকা শুধুমাত্র পূর্ণসংখ্যা s সংরক্ষণ করতে চান. আমরা একটি জেনেরিক টাইপ ব্যবহার করছি না. আমরা অ্যাড() পদ্ধতিতে একটি স্পষ্ট "ইনস্ট্যান্স অফ ইন্টিজার " চেক অন্তর্ভুক্ত করতে চাই না । যদি আমরা তা করি, তাহলে আমাদের পুরো ক্লাসটি শুধুমাত্র পূর্ণসংখ্যার জন্য উপযুক্ত হবে , এবং আমাদের বিশ্বের অন্যান্য ডেটা টাইপের জন্য একই ধরনের ক্লাস লিখতে হবে! আমরা আমাদের প্রোগ্রামারদের উপর নির্ভর করব, এবং আমরা যা চাই না এমন কিছু তারা যোগ না করে তা নিশ্চিত করতে কোডে একটি মন্তব্য করুন:

// Use this class ONLY with the Integer data type
public void add(Object o) {
   this.data[count] = o;
   count++;
}
একজন প্রোগ্রামার এই মন্তব্যটি মিস করেছেন এবং অসাবধানতাবশত সংখ্যার তালিকায় বেশ কয়েকটি স্ট্রিং রেখেছেন এবং তারপর তাদের যোগফল গণনা করেছেন:

public class Main {

   public static void main(String[] args) {

       MyListClass list = new MyListClass();
       list.add(100);
       list.add(200);
       list.add("Lolkek");
       list.add("Shalala");

       Integer sum1 = (Integer) list.getData()[0] + (Integer) list.getData()[1];
       System.out.println(sum1);

       Integer sum2 = (Integer) list.getData()[2] + (Integer) list.getData()[3];
       System.out.println(sum2);
   }
}
কনসোল আউটপুট:

300 
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 
      at Main.main (Main.java:14)
এই অবস্থার সবচেয়ে খারাপ অংশ কি? অবশ্যই প্রোগ্রামারের অসতর্কতা নয়। সবচেয়ে খারাপ দিক হল যে ভুল কোডটি আমাদের প্রোগ্রামের একটি গুরুত্বপূর্ণ জায়গায় শেষ হয়েছে এবং সফলভাবে সংকলিত হয়েছে। এখন আমরা কোড লেখার সময় বাগটির সম্মুখীন হব না, তবে শুধুমাত্র পরীক্ষার সময় (এবং এটিই সেরা পরিস্থিতি!) উন্নয়নের পরবর্তী পর্যায়ে বাগ সংশোধন করতে অনেক বেশি খরচ হয় — অর্থ এবং সময় উভয় ক্ষেত্রেই। এখানেই সুনির্দিষ্টভাবে জেনেরিক আমাদের উপকার করে: একটি জেনেরিক ক্লাস দুর্ভাগ্য প্রোগ্রামারকে এখনই ত্রুটি সনাক্ত করতে দেয়। প্রোগ্রাম সহজভাবে কম্পাইল হবে না!

import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Integer> myList1 = new ArrayList<>();
      
       myList1.add(100);
       myList1.add(100);
       myList1.add ("Lolkek"); // Error!
       myList1.add("Shalala"); // Error!
   }
}
প্রোগ্রামার অবিলম্বে তার ভুল বুঝতে পারে এবং সঙ্গে সঙ্গে ভাল হয়ে যায়। যাইহোক, এই ধরণের ত্রুটি দেখতে আমাদের নিজস্ব তালিকা শ্রেণী তৈরি করতে হবে না। সাধারণ অ্যারেলিস্ট থেকে কোণ বন্ধনীগুলি সরান এবং টাইপ করুন ( <Integer> )!

import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

      List list = new ArrayList();

      list.add(100);
      list.add(200);
      list.add("Lolkek");
      list.add("Shalala");

       System.out.println((Integer) list.get(0) + (Integer) list.get(1));
       System.out.println((Integer) list.get(2) + (Integer) list.get(3));
   }
}
কনসোল আউটপুট:

300 
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 
     at Main.main(Main.java:16)
অন্য কথায়, এমনকি জাভার "নেটিভ" মেকানিজম ব্যবহার করেও, আমরা এই ধরণের ভুল করতে পারি এবং একটি অনিরাপদ সংগ্রহ তৈরি করতে পারি। যাইহোক, যদি আমরা এই কোডটি একটি IDE-তে পেস্ট করি, আমরা একটি সতর্কতা পাব: "java.util.List-এর কাঁচা ধরনের সদস্য হিসাবে যোগ করার জন্য আনচেক করা কল" আমাদের বলা হয়েছে যে একটি আইটেম যোগ করার সময় কিছু ভুল হতে পারে এমন একটি সংগ্রহে যা একটি জেনেরিক টাইপের অভাব রয়েছে। কিন্তু শব্দগুচ্ছ "কাঁচা ধরনের" মানে কি? একটি কাঁচা টাইপ হল একটি জেনেরিক ক্লাস যার টাইপ সরানো হয়েছে। অন্য কথায়, List myList1 একটি কাঁচা টাইপএকটি কাঁচা টাইপের বিপরীত হল একটি জেনেরিক টাইপ — প্যারামিটারাইজড টাইপ(গুলি) এর ইঙ্গিত সহ একটি জেনেরিক ক্লাস । উদাহরণস্বরূপ, List<String> myList1. আপনি জিজ্ঞাসা করতে পারেন কেন ভাষা কাঁচা ধরনের ব্যবহারের অনুমতি দেয় ? কারণটা সহজ। জাভার নির্মাতারা সামঞ্জস্যের সমস্যা তৈরি এড়াতে ভাষার কাঁচা ধরনের জন্য সমর্থন ছেড়ে দিয়েছিলেন। জাভা 5.0 প্রকাশিত হওয়ার সময় (জেনারিকস প্রথম এই সংস্করণে উপস্থিত হয়েছিল), কাঁচা প্রকারগুলি ব্যবহার করে ইতিমধ্যে প্রচুর কোড লেখা হয়েছে । ফলস্বরূপ, এই প্রক্রিয়াটি আজও সমর্থিত। আমরা বারবার পাঠগুলিতে জোশুয়া ব্লচের ক্লাসিক বই "কার্যকর জাভা" উল্লেখ করেছি। ভাষার স্রষ্টাদের একজন হিসাবে, তিনি তার বইতে কাঁচা প্রকার এবং জেনেরিক প্রকারগুলি এড়িয়ে যাননি।জাভাতে জেনেরিক কি?  - 2বইটির 23 অধ্যায়ের একটি খুব বাকপটু শিরোনাম রয়েছে: "নতুন কোডে কাঁচা প্রকারগুলি ব্যবহার করবেন না" এটি আপনার মনে রাখা দরকার। জেনেরিক ক্লাস ব্যবহার করার সময়, জেনেরিক টাইপকে কখনই কাঁচা টাইপে পরিণত করবেন না ।

জেনেরিক পদ্ধতি

জাভা আপনাকে তথাকথিত জেনেরিক পদ্ধতি তৈরি করে পৃথক পদ্ধতির প্যারামিটারাইজ করতে দেয়। এই ধরনের পদ্ধতি কিভাবে সহায়ক? সর্বোপরি, তারা সহায়ক যে তারা আপনাকে বিভিন্ন ধরণের পদ্ধতি পরামিতিগুলির সাথে কাজ করতে দেয়। যদি একই যুক্তি নিরাপদে বিভিন্ন ধরনের প্রয়োগ করা যায়, একটি জেনেরিক পদ্ধতি একটি দুর্দান্ত সমাধান হতে পারে। এটি একটি খুব সাধারণ উদাহরণ বিবেচনা করুন: ধরুন আমাদের কাছে myList1 নামে একটি তালিকা রয়েছে । আমরা তালিকা থেকে সমস্ত মান মুছে ফেলতে চাই এবং নতুন মান দিয়ে সমস্ত খালি স্থান পূরণ করতে চাই। জেনেরিক পদ্ধতির সাথে আমাদের ক্লাসটি কেমন দেখায় তা এখানে:

public class TestClass {

   public static <T> void fill(List<T> list, T val) {
       for (int i = 0; i < list.size(); i++)
           list.set(i, val);
   }

   public static void main(String[] args) {

       List<String> strings = new ArrayList<>();
       strings.add("Old String 1");
       strings.add("Old String 2");
       strings.add("Old String 3");

       fill(strings, "New String");

       System.out.println(strings);

       List<Integer> numbers = new ArrayList<>();
       numbers.add(1);
       numbers.add(2);
       numbers.add(3);

       fill(numbers, 888);
       System.out.println(numbers);
   }
}
সিনট্যাক্সে মনোযোগ দিন। এটা একটু অস্বাভাবিক দেখায়:

public static <T> void fill(List<T> list, T val)
আমরা রিটার্ন টাইপের আগে <T> লিখি। এটি ইঙ্গিত দেয় যে আমরা একটি জেনেরিক পদ্ধতি নিয়ে কাজ করছি৷ এই ক্ষেত্রে, পদ্ধতিটি একটি ইনপুট হিসাবে 2টি পরামিতি গ্রহণ করে: T অবজেক্টের একটি তালিকা এবং আরেকটি পৃথক T অবজেক্ট। <T> ব্যবহার করে, আমরা পদ্ধতির পরামিতি প্রকারগুলিকে প্যারামিটারাইজ করি: আমরা স্ট্রিং এবং একটি পূর্ণসংখ্যার তালিকায় পাস করতে পারি না। স্ট্রিং এবং একটি স্ট্রিং এর একটি তালিকা, পূর্ণসংখ্যা এবং একটি পূর্ণসংখ্যার একটি তালিকা, আমাদের নিজস্ব বিড়াল বস্তুর একটি তালিকা এবং আরেকটি বিড়াল বস্তু - আমাদের যা করতে হবে। main () পদ্ধতিটি ব্যাখ্যা করে কিভাবে fill() পদ্ধতিটি বিভিন্ন ধরণের ডেটার সাথে কাজ করার জন্য সহজেই ব্যবহার করা যেতে পারে। প্রথমে, আমরা পদ্ধতিটি ব্যবহার করি স্ট্রিং-এর তালিকা এবং একটি স্ট্রিং ইনপুট হিসাবে, এবং তারপরে পূর্ণসংখ্যা এবং একটি পূর্ণসংখ্যার তালিকা সহ। কনসোল আউটপুট:

[New String, New String, New String] [888, 888, 888]
কল্পনা করুন যদি আমাদের জেনেরিক পদ্ধতি না থাকে এবং 30টি ভিন্ন শ্রেণীর জন্য fill() পদ্ধতির যুক্তির প্রয়োজন হয়। বিভিন্ন ডাটা টাইপের জন্য আমাদের একই পদ্ধতি 30 বার লিখতে হবে! কিন্তু জেনেরিক পদ্ধতির জন্য ধন্যবাদ, আমরা আমাদের কোড পুনরায় ব্যবহার করতে পারি! :)

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

আপনি স্ট্যান্ডার্ড জাভা লাইব্রেরিতে দেওয়া জেনেরিক ক্লাসের মধ্যে সীমাবদ্ধ নন — আপনি নিজের তৈরি করতে পারেন! এখানে একটি সহজ উদাহরণ:

public class Box<T> {

   private T t;

   public void set(T t) {
       this.t = t;
   }

   public T get() {
       return t;
   }

   public static void main(String[] args) {

       Box<String> stringBox = new Box<>();

       stringBox.set("Old String");
       System.out.println(stringBox.get());
       stringBox.set("New String");

       System.out.println(stringBox.get());
      
       stringBox.set(12345); // Compilation error!
   }
}
আমাদের বক্স<T> ক্লাস একটি জেনেরিক ক্লাস। একবার আমরা তৈরি করার সময় একটি ডেটা টাইপ ( <T> ) বরাদ্দ করি, আমরা আর এতে অন্য ধরনের বস্তু স্থাপন করতে পারি না। এটি উদাহরণে দেখা যেতে পারে। আমাদের অবজেক্ট তৈরি করার সময়, আমরা ইঙ্গিত দিয়েছিলাম যে এটি স্ট্রিংগুলির সাথে কাজ করবে:

Box<String> stringBox = new Box<>();
এবং কোডের শেষ লাইনে, যখন আমরা বাক্সের ভিতরে 12345 নম্বর রাখার চেষ্টা করি, আমরা একটি সংকলন ত্রুটি পাই! এটা যে সহজ! আমরা আমাদের নিজস্ব জেনেরিক ক্লাস তৈরি করেছি! :) সেই সাথে, আজকের পাঠ শেষ হয়। কিন্তু আমরা জেনেরিককে বিদায় দিচ্ছি না! পরবর্তী পাঠগুলিতে, আমরা আরও উন্নত বৈশিষ্ট্য সম্পর্কে কথা বলব, তাই আপনি দূরে যাবেন না! ) আপনি যা শিখেছেন তা শক্তিশালী করার জন্য, আমরা আপনাকে আমাদের জাভা কোর্স থেকে একটি ভিডিও পাঠ দেখার পরামর্শ দিই
আপনার পড়াশোনায় সাফল্যের সেরা! :)
মন্তব্য
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION