জাভায় জেনেরিক্সের অ্যাডভান্সড টেকনিকগুলো ব্যবহার করে আরও ফ্লেক্সিবল এবং শক্তিশালী কোড লেখা যায়। এগুলো বড় স্কেল প্রজেক্টে কোডের পুনঃব্যবহারযোগ্যতা এবং টাইপ সেফটি নিশ্চিত করতে সাহায্য করে। এই নিবন্ধে আমরা অ্যাডভান্সড জেনেরিক টেকনিকের কিছু গুরুত্বপূর্ণ দিক নিয়ে আলোচনা করব।
১. Recursive Type Bound
Recursive টাইপ বাউন্ড এমন একটি কৌশল যেখানে টাইপ প্যারামিটার নিজেই নিজের সাথে সম্পর্কিত হয়। এটি সাধারণত কম্পারিজন বা র্যাঙ্কিং সিস্টেম তৈরি করার জন্য ব্যবহৃত হয়।
উদাহরণ: Comparable Interface
public class Box<T extends Comparable<T>> {
private T value;
public Box(T value) {
this.value = value;
}
public boolean isGreaterThan(Box<T> other) {
return value.compareTo(other.value) > 0;
}
public static void main(String[] args) {
Box<Integer> box1 = new Box<>(10);
Box<Integer> box2 = new Box<>(20);
System.out.println(box1.isGreaterThan(box2)); // false
}
}
২. Intersection Types (Multiple Bounds)
একাধিক টাইপ বাউন্ড ব্যবহার করে একটি টাইপ প্যারামিটার নির্দিষ্ট কয়েকটি ইন্টারফেস বা ক্লাসের বৈশিষ্ট্য ধারণ করতে পারে।
Syntax:
<T extends ClassA & InterfaceB & InterfaceC>
উদাহরণ:
interface Shape {
void draw();
}
interface Colored {
String getColor();
}
public class Box<T extends Shape & Colored> {
private T item;
public Box(T item) {
this.item = item;
}
public void displayInfo() {
item.draw();
System.out.println("Color: " + item.getColor());
}
public static void main(String[] args) {
class Circle implements Shape, Colored {
@Override
public void draw() {
System.out.println("Drawing Circle");
}
@Override
public String getColor() {
return "Red";
}
}
Box<Circle> circleBox = new Box<>(new Circle());
circleBox.displayInfo();
}
}
আউটপুট:
Drawing Circle
Color: Red
৩. Generic Methods in Static Context
জেনেরিক মেথড স্ট্যাটিক কনটেক্সটে ব্যবহার করা যায়, যেখানে পুরো ক্লাস জেনেরিক না হলেও মেথডটি জেনেরিক হতে পারে।
উদাহরণ:
public class Utility {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
public static void main(String[] args) {
Integer[] intArray = {1, 2, 3};
String[] stringArray = {"Java", "Generics"};
printArray(intArray);
printArray(stringArray);
}
}
আউটপুট:
1
2
3
Java
Generics
৪. Generic Class with Multiple Parameters
একাধিক টাইপ প্যারামিটার ব্যবহার করে ক্লাস বা মেথড আরও ফ্লেক্সিবল করা যায়।
Syntax:
public class ClassName<K, V> {
// Implementation
}
উদাহরণ:
public class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public static void main(String[] args) {
Pair<String, Integer> pair = new Pair<>("Age", 25);
System.out.println("Key: " + pair.getKey());
System.out.println("Value: " + pair.getValue());
}
}
আউটপুট:
Key: Age
Value: 25
৫. Generic Type Inference
Java Compiler অনেক সময় জেনেরিক টাইপ নিজেই ইনফার (অনুমান) করতে পারে।
উদাহরণ:
public class GenericInference {
public static <T> T getFirstElement(T[] array) {
return array[0];
}
public static void main(String[] args) {
String[] strings = {"Java", "Generics"};
Integer[] integers = {1, 2, 3};
System.out.println(getFirstElement(strings)); // Java
System.out.println(getFirstElement(integers)); // 1
}
}
৬. Wildcards in Advanced Use Cases
Wildcards (?) ব্যবহারের মাধ্যমে জেনেরিক টাইপ আরও ফ্লেক্সিবল করা যায়।
Unbounded Wildcards:
public static void printList(List<?> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
Upper-Bounded Wildcards:
public static void printNumbers(List<? extends Number> list) {
for (Number num : list) {
System.out.println(num);
}
}
Lower-Bounded Wildcards:
public static void addNumbers(List<? super Integer> list) {
list.add(10);
}
৭. Generic Builder Pattern
Generic Builder Pattern জেনেরিক টাইপের ভিত্তিতে একটি ফ্লুয়েন্ট API তৈরিতে ব্যবহৃত হয়।
উদাহরণ:
public class Builder<T> {
private T instance;
public Builder(T instance) {
this.instance = instance;
}
public Builder<T> with(Consumer<T> setter) {
setter.accept(instance);
return this;
}
public T build() {
return instance;
}
public static void main(String[] args) {
class User {
String name;
int age;
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
User user = new Builder<>(new User())
.with(u -> u.name = "Alice")
.with(u -> u.age = 30)
.build();
System.out.println(user);
}
}
আউটপুট:
User{name='Alice', age=30}
জাভার অ্যাডভান্সড জেনেরিক টেকনিকগুলো টাইপ সেফ, ফ্লেক্সিবল, এবং মডুলার কোড লেখার সুযোগ দেয়। এই টেকনিকগুলো ডেভেলপারদের বড় স্কেল প্রজেক্টে আরও কার্যকর এবং পরিষ্কার কোড তৈরি করতে সাহায্য করে।
জাভায় Recursive Type Bounds এমন একটি কৌশল যেখানে একটি জেনেরিক টাইপ নিজেকে সীমাবদ্ধ করার জন্য ব্যবহার করা হয়। এটি সাধারণত self-referencing টাইপের জন্য ব্যবহৃত হয়, যেখানে একটি জেনেরিক ক্লাস বা ইন্টারফেসের টাইপ প্যারামিটার সেই একই ক্লাস বা ইন্টারফেসের সাথে সম্পর্কিত হয়।
Recursive Type Bounds এর সিনট্যাক্স
<T extends Comparable<T>>
এখানে:
Tএকটি জেনেরিক টাইপ প্যারামিটার।T extends Comparable<T>নির্দেশ করে যেTঅবশ্যইComparableইন্টারফেসকে ইমপ্লিমেন্ট করবে এবংTটাইপের অবজেক্টের সাথে তুলনা করার ক্ষমতা রাখবে।
Recursive Type Bounds কেন প্রয়োজন?
- Comparability নিশ্চিত করা: জেনেরিক টাইপের মধ্যে তুলনা (comparison) করার জন্য।
- Type Safety: টাইপ-সেইফ কোড লেখা নিশ্চিত করা।
- Reusable এবং Generic Methods/Classes তৈরি করা: বিভিন্ন টাইপের জন্য একই কোড পুনঃব্যবহার করা যায়।
Recursive Type Bounds এর উদাহরণ
1. Comparable Interface এর সাথে ব্যবহার
class Box<T extends Comparable<T>> {
private T item;
public Box(T item) {
this.item = item;
}
public T getItem() {
return item;
}
// Compare two items
public int compareTo(Box<T> otherBox) {
return item.compareTo(otherBox.getItem());
}
}
public class RecursiveBoundsExample {
public static void main(String[] args) {
Box<Integer> box1 = new Box<>(10);
Box<Integer> box2 = new Box<>(20);
int result = box1.compareTo(box2);
if (result < 0) {
System.out.println("box1 is smaller than box2");
} else if (result > 0) {
System.out.println("box1 is greater than box2");
} else {
System.out.println("box1 is equal to box2");
}
}
}
আউটপুট:
box1 is smaller than box2
2. Recursive Type Bounds এবং Generic Methods
import java.util.Arrays;
import java.util.List;
public class RecursiveTypeMethod {
// Method to find the maximum element
public static <T extends Comparable<T>> T findMax(List<T> items) {
T max = items.get(0);
for (T item : items) {
if (item.compareTo(max) > 0) {
max = item;
}
}
return max;
}
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(5, 10, 15, 2, 8);
System.out.println("Maximum number: " + findMax(numbers)); // Output: 15
List<String> words = Arrays.asList("apple", "orange", "banana", "grape");
System.out.println("Maximum word: " + findMax(words)); // Output: orange
}
}
3. Recursive Type Bounds এবং Custom Class
class Shape<T extends Shape<T>> {
public boolean isLargerThan(T other) {
return this.getArea() > other.getArea();
}
public double getArea() {
return 0.0; // Default implementation
}
}
class Circle extends Shape<Circle> {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}
public class RecursiveCustomClass {
public static void main(String[] args) {
Circle c1 = new Circle(3);
Circle c2 = new Circle(4);
System.out.println("Is c1 larger than c2? " + c1.isLargerThan(c2)); // Output: false
}
}
Recursive Type Bounds এর সুবিধা
- Reusable Code: একই জেনেরিক কোড একাধিক টাইপের জন্য ব্যবহার করা যায়।
- Type Safety: টাইপ মিসম্যাচ এবং রানটাইম ত্রুটি এড়ানো যায়।
- Compile-Time Checking: কম্পাইল-টাইমে টাইপ সংক্রান্ত ভুল ধরা যায়।
Recursive Type Bounds এর সীমাবদ্ধতা
- জটিলতা: নতুনদের জন্য সিনট্যাক্স এবং ধারণা বুঝতে কিছুটা কঠিন।
- Type Erasure: রানটাইমে জেনেরিক টাইপ ইনফরমেশন মুছে যায়, ফলে কিছু সীমাবদ্ধতা থেকে যায়।
Recursive Type Bounds জেনেরিক্সের একটি শক্তিশালী ফিচার যা টাইপ-সেইফ এবং পুনঃব্যবহারযোগ্য কোড তৈরি করতে সাহায্য করে। এটি বিশেষত Comparable বা Custom Hierarchy সম্পর্কিত ক্লাস এবং মেথড তৈরির ক্ষেত্রে কার্যকর। সঠিকভাবে ব্যবহার করলে এটি কোডের কার্যকারিতা এবং স্থায়িত্ব বাড়াতে গুরুত্বপূর্ণ ভূমিকা পালন করে।
Generic Singleton Factory Method এমন একটি প্যাটার্ন যেখানে একটি সিঙ্গলটন অবজেক্ট তৈরি এবং প্রদান করা হয়, যা জেনেরিক টাইপ ব্যবহার করে টাইপ-সেইফটি নিশ্চিত করে। এটি বিশেষত কোডের পুনঃব্যবহারযোগ্যতা বাড়ায় এবং টাইপ সংক্রান্ত ত্রুটি কমায়।
Generic Singleton Factory Method কী?
- Generic Singleton: এটি একটি সিঙ্গলটন অবজেক্ট যা একটি নির্দিষ্ট জেনেরিক টাইপের জন্য কাজ করে।
- Factory Method: একটি মেথড যা সিঙ্গলটন ইনস্ট্যান্স তৈরি বা রিটার্ন করে।
- উদ্দেশ্য: কোডকে টাইপ-সেইফ করার পাশাপাশি একাধিক টাইপের জন্য একটি সাধারণ সিঙ্গলটন অবজেক্ট প্রদান করা।
Generic Singleton Factory Method এর প্রয়োগ
1. Generic Singleton Class
public class SingletonFactory {
// Private static instance (generic)
private static final SingletonFactory INSTANCE = new SingletonFactory();
// Private constructor to prevent instantiation
private SingletonFactory() {}
// Generic Factory Method
public static <T> T getInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException {
return clazz.newInstance();
}
}
ব্যবহারের উদাহরণ
2. Simple Example
public class Main {
public static void main(String[] args) {
try {
// Getting instances of different classes
String strInstance = SingletonFactory.getInstance(String.class);
Integer intInstance = SingletonFactory.getInstance(Integer.class);
System.out.println("String Instance: " + strInstance);
System.out.println("Integer Instance: " + intInstance);
} catch (Exception e) {
e.printStackTrace();
}
}
}
আউটপুট:
String Instance:
Integer Instance: 0
Refined Implementation: Singleton with Predefined Instances
কখনও কখনও পূর্বনির্ধারিত ইনস্ট্যান্স ব্যবহার করে টাইপ অনুযায়ী সিঙ্গলটন তৈরি করা হয়। উদাহরণস্বরূপ:
3. Predefined Singleton Instances
import java.util.HashMap;
import java.util.Map;
public class SingletonFactory {
// Map to store singletons
private static final Map<Class<?>, Object> instances = new HashMap<>();
static {
instances.put(String.class, "");
instances.put(Integer.class, 0);
instances.put(Double.class, 0.0);
}
// Generic Factory Method
@SuppressWarnings("unchecked")
public static <T> T getInstance(Class<T> clazz) {
return (T) instances.get(clazz);
}
}
4. ব্যবহার:
public class Main {
public static void main(String[] args) {
// Getting predefined instances
String str = SingletonFactory.getInstance(String.class);
Integer num = SingletonFactory.getInstance(Integer.class);
Double dbl = SingletonFactory.getInstance(Double.class);
System.out.println("String Instance: " + str);
System.out.println("Integer Instance: " + num);
System.out.println("Double Instance: " + dbl);
}
}
আউটপুট:
String Instance:
Integer Instance: 0
Double Instance: 0.0
Advanced Example: Thread-Safe Generic Singleton Factory
5. Thread-Safe Implementation
import java.util.concurrent.ConcurrentHashMap;
public class ThreadSafeSingletonFactory {
private static final ConcurrentHashMap<Class<?>, Object> instances = new ConcurrentHashMap<>();
// Generic Factory Method
public static <T> T getInstance(Class<T> clazz) {
return (T) instances.computeIfAbsent(clazz, cls -> {
try {
return cls.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
}
6. ব্যবহার:
public class Main {
public static void main(String[] args) {
String str1 = ThreadSafeSingletonFactory.getInstance(String.class);
String str2 = ThreadSafeSingletonFactory.getInstance(String.class);
Integer num1 = ThreadSafeSingletonFactory.getInstance(Integer.class);
Integer num2 = ThreadSafeSingletonFactory.getInstance(Integer.class);
System.out.println("String Instances are same: " + (str1 == str2));
System.out.println("Integer Instances are same: " + (num1 == num2));
}
}
আউটপুট:
String Instances are same: true
Integer Instances are same: true
Generic Singleton Factory Method এর সুবিধা
- টাইপ-সেইফটি: প্রয়োজনীয় টাইপ রানটাইমে না জানালেও, কম্পাইল টাইমে টাইপ চেকিং নিশ্চিত করা হয়।
- কোড পুনঃব্যবহারযোগ্যতা: একই প্যাটার্ন দিয়ে বিভিন্ন টাইপের জন্য কাজ করা যায়।
- সিঙ্গল ইনস্ট্যান্স: একটি নির্দিষ্ট টাইপের জন্য একই ইনস্ট্যান্স প্রদান করা হয়।
- থ্রেড-সেফটি: থ্রেড-সেফ ডেটা স্ট্রাকচার ব্যবহার করে কনকারেন্ট প্রোগ্রামিং সহজ হয়।
- Generic Singleton Factory Method টাইপ-সেইফ এবং ডাইনামিক প্রোগ্রামিংয়ের জন্য গুরুত্বপূর্ণ।
- এটি বড় স্কেলের প্রজেক্টে কোড রিডেবিলিটি, মডুলারিটি, এবং পারফরম্যান্স উন্নত করতে ব্যবহৃত হয়।
- Thread-safe এবং Predefined Instance প্যাটার্ন বড় অ্যাপ্লিকেশন ডেভেলপমেন্টে কার্যকর।
Builder Pattern হলো একটি ডিজাইন প্যাটার্ন যা জটিল অবজেক্ট তৈরির জন্য ধাপে ধাপে একটি পদ্ধতি প্রদান করে। জেনেরিক্স ব্যবহার করে এই প্যাটার্ন আরও ফ্লেক্সিবল ও পুনঃব্যবহারযোগ্য করা যায়।
Generics ব্যবহার করে Builder Pattern এর সুবিধা
- টাইপ সেফটি নিশ্চিত করে: জেনেরিক্সের মাধ্যমে টাইপ মিসম্যাচ সমস্যা এড়ানো যায়।
- পুনঃব্যবহারযোগ্য কোড: বিভিন্ন টাইপের অবজেক্ট তৈরি করার জন্য একই বিল্ডার ব্যবহার করা যায়।
- ফ্লুয়েন্ট API: কোড পড়া ও ব্যবহার করা সহজ হয়।
Generics সহ Builder Pattern এর গঠন
1. Basic Generic Builder Pattern
উদাহরণ:
public class GenericBuilder<T> {
private T instance;
public GenericBuilder(T instance) {
this.instance = instance;
}
public T build() {
return instance;
}
public GenericBuilder<T> with(Consumer<T> consumer) {
consumer.accept(instance);
return this;
}
public static void main(String[] args) {
// Example of building a StringBuilder using the generic builder
StringBuilder sb = new GenericBuilder<>(new StringBuilder())
.with(builder -> builder.append("Hello"))
.with(builder -> builder.append(", Generics!"))
.build();
System.out.println(sb); // Output: Hello, Generics!
}
}
2. Generics সহ Complex Builder Pattern
উদাহরণ:
public class GenericBuilder<T> {
private final T instance;
private GenericBuilder(Class<T> clazz) {
try {
this.instance = clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException("Error creating instance", e);
}
}
public static <T> GenericBuilder<T> of(Class<T> clazz) {
return new GenericBuilder<>(clazz);
}
public GenericBuilder<T> with(Consumer<T> consumer) {
consumer.accept(instance);
return this;
}
public T build() {
return instance;
}
}
// Example class to build
class User {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
// Main method
public class Main {
public static void main(String[] args) {
User user = GenericBuilder.of(User.class)
.with(u -> u.setName("Alice"))
.with(u -> u.setAge(25))
.build();
System.out.println(user); // Output: User{name='Alice', age=25}
}
}
3. Inheritance সহ Generics এবং Builder Pattern
জেনেরিক বিল্ডার প্যাটার্ন ইনহেরিটেন্স সমর্থন করে।
উদাহরণ:
class Person {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{name='" + name + "'}";
}
}
class Employee extends Person {
private String position;
public void setPosition(String position) {
this.position = position;
}
@Override
public String toString() {
return super.toString() + ", position='" + position + "'";
}
}
class PersonBuilder<T extends Person, B extends PersonBuilder<T, B>> {
protected final T instance;
public PersonBuilder(T instance) {
this.instance = instance;
}
public B withName(String name) {
instance.setName(name);
return (B) this;
}
public T build() {
return instance;
}
}
class EmployeeBuilder extends PersonBuilder<Employee, EmployeeBuilder> {
public EmployeeBuilder() {
super(new Employee());
}
public EmployeeBuilder withPosition(String position) {
instance.setPosition(position);
return this;
}
}
// Main method
public class Main {
public static void main(String[] args) {
Employee employee = new EmployeeBuilder()
.withName("Bob")
.withPosition("Developer")
.build();
System.out.println(employee); // Output: Person{name='Bob'}, position='Developer'
}
}
Generics এর মাধ্যমে Builder Pattern:
- Reusable এবং Flexible হয়।
- টাইপ সেফ কোড তৈরি নিশ্চিত করে।
- কমপ্লেক্স ক্লাসের ইনহেরিটেন্স ব্যবস্থাপনা সহজ করে।
এই প্যাটার্ন বড় ও জটিল অবজেক্ট তৈরির জন্য অত্যন্ত কার্যকর এবং কোড রিডেবিলিটি বাড়ায়।
Java Generics জাভা প্রোগ্রামিংয়ে টাইপ সেফটি নিশ্চিত করার পাশাপাশি কোডের পুনরায় ব্যবহারযোগ্যতা এবং রিডেবিলিটি বাড়ানোর জন্য ব্যবহৃত হয়। এর মাধ্যমে কম্পাইল টাইমে টাইপ চেকিং নিশ্চিত হয় এবং রানটাইম টাইপ ক্যাস্টিং ত্রুটি (ClassCastException) এড়ানো যায়। বাস্তব জীবনে জেনেরিক্স বিভিন্ন গুরুত্বপূর্ণ ক্ষেত্রে ব্যবহার করা হয় এবং উন্নত টেকনিকের মাধ্যমে আরও কার্যকর করা যায়।
Real-Life Use Cases of Java Generics
1. Collections API
Java Collections Framework এর সমস্ত ক্লাস ও ইন্টারফেস জেনেরিক্স ব্যবহার করে টাইপ সেফ ডেটা স্ট্রাকচার সরবরাহ করে।
উদাহরণ:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> names = new ArrayList<>(); // Type-safe list
names.add("Alice");
names.add("Bob");
for (String name : names) {
System.out.println(name);
}
}
}
ব্যবহার: Collections API ব্যবহার করে টাইপ সেফ ডেটা স্ট্রাকচার তৈরি করা সহজ হয়।
2. Custom Generic Classes
জেনেরিক ক্লাস তৈরি করে আমরা ডেটা টাইপ নির্দিষ্ট না করেও একই কোড পুনরায় ব্যবহার করতে পারি।
উদাহরণ:
public class Box<T> {
private T item;
public void setItem(T item) {
this.item = item;
}
public T getItem() {
return item;
}
public static void main(String[] args) {
Box<String> stringBox = new Box<>();
stringBox.setItem("Hello");
Box<Integer> intBox = new Box<>();
intBox.setItem(123);
System.out.println("String: " + stringBox.getItem());
System.out.println("Integer: " + intBox.getItem());
}
}
ব্যবহার: মাল্টি-পারপাস ক্লাস তৈরিতে সহায়ক।
3. Generic Methods
জেনেরিক মেথড ব্যবহার করে একটি নির্দিষ্ট ডেটা টাইপের উপর নির্ভর না করে কাজ করা সম্ভব।
উদাহরণ:
public class Utility {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
public static void main(String[] args) {
String[] strArray = {"A", "B", "C"};
Integer[] intArray = {1, 2, 3};
printArray(strArray);
printArray(intArray);
}
}
ব্যবহার: সাধারণ কাজের জন্য পুনরায় ব্যবহারযোগ্য মেথড তৈরি।
4. DAO (Data Access Object) Pattern
ডেটাবেস থেকে ডেটা পড়া এবং লেখার জন্য জেনেরিক DAO ক্লাস ব্যবহার করা হয়।
উদাহরণ:
public class GenericDAO<T> {
public void save(T entity) {
// Logic to save entity in the database
}
public T findById(int id) {
// Logic to find entity by ID
return null;
}
}
public class Main {
public static void main(String[] args) {
GenericDAO<User> userDAO = new GenericDAO<>();
User user = new User("Alice");
userDAO.save(user);
GenericDAO<Product> productDAO = new GenericDAO<>();
Product product = new Product("Laptop");
productDAO.save(product);
}
}
ব্যবহার: ডেটাবেস সংক্রান্ত কাজের জন্য পুনরায় ব্যবহারযোগ্য DAO তৈরি।
5. Functional Programming with Generics
Streams API এবং Functional Interfaces জেনেরিক্স ব্যবহার করে ল্যাম্বডা এক্সপ্রেশন ও ফাংশনাল প্রোগ্রামিংকে আরও সহজ করে।
উদাহরণ:
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println); // Output: 2, 4
}
}
ব্যবহার: টাইপ-সেফ ফাংশনাল প্রোগ্রামিং নিশ্চিত।
Advanced Techniques in Java Generics
1. Bounded Types
জেনেরিক টাইপ প্যারামিটারগুলো সীমিত করতে extends ব্যবহার করা হয়।
উদাহরণ:
public class Calculator<T extends Number> {
public double add(T a, T b) {
return a.doubleValue() + b.doubleValue();
}
public static void main(String[] args) {
Calculator<Integer> intCalc = new Calculator<>();
System.out.println(intCalc.add(10, 20));
Calculator<Double> doubleCalc = new Calculator<>();
System.out.println(doubleCalc.add(5.5, 2.2));
}
}
ব্যবহার: নির্দিষ্ট টাইপের উপর কাজ করতে সহায়ক।
2. Wildcard Generics
Wildcard (?) দিয়ে জেনেরিক টাইপের সীমাবদ্ধতা নির্ধারণ করা যায়।
উদাহরণ:
import java.util.List;
public class WildcardExample {
public static void printList(List<?> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
public static void main(String[] args) {
List<String> strings = List.of("A", "B", "C");
List<Integer> integers = List.of(1, 2, 3);
printList(strings);
printList(integers);
}
}
ব্যবহার: বিভিন্ন ধরনের ডেটা হ্যান্ডেল করতে।
3. Multiple Bounds
একাধিক বাউন্ড ব্যবহার করে জেনেরিক টাইপকে আরও নির্দিষ্ট করা যায়।
উদাহরণ:
public class MultiBound<T extends Number & Comparable<T>> {
public T findMax(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
public static void main(String[] args) {
MultiBound<Integer> mb = new MultiBound<>();
System.out.println("Max: " + mb.findMax(10, 20));
}
}
ব্যবহার: টাইপ সেফ এবং সীমিত কাজের জন্য।
4. Generic Enum Types
জেনেরিক টাইপ ব্যবহার করে Enums এর ক্ষমতা বাড়ানো যায়।
উদাহরণ:
public enum Operation<T extends Number> {
ADD {
public T apply(T a, T b) {
return (T) Double.valueOf(a.doubleValue() + b.doubleValue());
}
},
SUBTRACT {
public T apply(T a, T b) {
return (T) Double.valueOf(a.doubleValue() - b.doubleValue());
}
};
public abstract T apply(T a, T b);
}
Java Generics বাস্তব জীবনের সমস্যাগুলি সমাধানের জন্য একটি অত্যন্ত কার্যকরী টুল:
- এটি টাইপ সেফটি নিশ্চিত করে।
- পুনরায় ব্যবহারযোগ্য কোড তৈরি করতে সাহায্য করে।
- উন্নত টেকনিক, যেমন Wildcard Generics, Bounded Types, এবং Multiple Bounds ব্যবহার করে জটিল সমস্যা সমাধান সহজ হয়।
জেনেরিক্সের শক্তিশালী ব্যবহার দক্ষ ও কার্যকর সফটওয়্যার তৈরি করতে সহায়ক।
Read more