Class.newInstance() ব্যবহার করে একটি বস্তু তৈরির উদাহরণ

কল্পনা করুন যে আপনাকে প্রতিফলন ব্যবহার করে একটি বস্তু তৈরি করার জন্য নিয়োগ দেওয়া হয়েছে। আমরা কি শুরু করব?

আমরা যে ক্লাসটি ইনস্ট্যান্ট করতে চাই তার জন্য কোড লিখে শুরু করব:

public class Employee {
    private String name;
    private String lastName;
    private int age;

    {
        age = -1;
        name = "Rob";
        surname = "Stark";
    }

    public Employee(String name, String surname, int age) {
        this.name = name;
        this.surname = surname;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return lastName;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", surname='" + surname + '\'' +
                ", age=" + age +
                '}';
    }
}

এটি হবে আমাদের ক্লাস — বিভিন্ন ক্ষেত্র সহ, প্যারামিটার সহ একটি কনস্ট্রাক্টর, গেটার এবং সেটার্স, একটি toString() পদ্ধতি এবং একটি ইনিশিয়ালাইজেশন ব্লক। এখন দ্বিতীয় অংশে যাওয়া যাক: প্রতিফলন ব্যবহার করে একটি বস্তু তৈরি করা। আমরা যে প্রথম পদ্ধতির দিকে তাকাব সেটি Class.newInstance() ব্যবহার করবে ।

public class Main {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        Employee employee = Employee.class.newInstance();
        System.out.println("age is " + employee.getAge());
    }
}

চমৎকার! আসুন আমাদের কোডটি চালান এবং বয়সটি প্রদর্শিত হবে তা দেখুন। কিন্তু আমরা একটি অনুপস্থিত ডিফল্ট কনস্ট্রাক্টর সম্পর্কে একটি ত্রুটি পেতে. দেখা যাচ্ছে যে এই পদ্ধতিটি শুধুমাত্র ডিফল্ট কনস্ট্রাক্টর ব্যবহার করে তৈরি করা একটি বস্তু পেতে দেয়। আমাদের ক্লাসের জন্য একটি ডিফল্ট কনস্ট্রাক্টর যোগ করুন এবং কোডটি আবার পরীক্ষা করুন।

ভুল বার্তা:

নতুন কনস্ট্রাক্টরের কোড

public Employee() { }

কনস্ট্রাক্টর যোগ করার পরে, এখানে আউটপুট আছে:

বয়স 1

দারুণ! আমরা এই পদ্ধতিটি কীভাবে কাজ করে তা খুঁজে বের করেছি। এখন এর ফণা অধীনে কটাক্ষপাত করা যাক. ডকুমেন্টেশন ওপেন ক্র্যাক করে, আমরা দেখতে পাই যে আমাদের পদ্ধতিটি ইতিমধ্যেই অবমূল্যায়িত হয়েছে :

এটি InstantiationException এবং IllegalAccessException ও ফেলতে পারে । তদনুসারে, ডকুমেন্টেশন পরামর্শ দেয় যে আমরা একটি অবজেক্ট তৈরি করার অন্য উপায় ব্যবহার করি, যথা Constructor.newInstance()কনস্ট্রাক্টর ক্লাস কিভাবে কাজ করে তা বিস্তারিতভাবে বিশ্লেষণ করা যাক ।

getConstructors এবং getDeclaredConstructors পদ্ধতি

কনস্ট্রাক্টর ক্লাসের সাথে কাজ করার জন্য , আমাদের প্রথমে একটি উদাহরণ পেতে হবে। এর জন্য আমাদের কাছে দুটি পদ্ধতি রয়েছে: getConstructors এবং getDeclaredConstructors

প্রথমটি পাবলিক কনস্ট্রাক্টরের একটি অ্যারে প্রদান করে এবং দ্বিতীয়টি সমস্ত শ্রেণীর কনস্ট্রাক্টরের একটি অ্যারে প্রদান করে।

আসুন আমাদের ক্লাসকে কিছু গোপনীয়তা দেওয়া যাক, বা এর পরিবর্তে, এই পদ্ধতিগুলি কীভাবে কাজ করে তা প্রদর্শন করতে সাহায্য করার জন্য কিছু ব্যক্তিগত কনস্ট্রাক্টর তৈরি করি।

আসুন কিছু প্রাইভেট কনস্ট্রাক্টর যোগ করি:

private Employee(String name, String surname) {
    this.name = name;
    this.lastName = lastName;
}

কোডের দিকে তাকিয়ে, নোট করুন যে কনস্ট্রাক্টরগুলির মধ্যে একটি ব্যক্তিগত:

আসুন আমাদের পদ্ধতি পরীক্ষা করা যাক:

public class Main {
	  public static void main(String[] args) {
	      Class employeeClass = Employee.class;

	      System.out.println("getConstructors:");
	      printAllConstructors(employeeClass);

	      System.out.println("\n" +"getDeclaredConstructors:");
	      printDeclaredConstructors(employeeClass);
	  }

	  static void printDeclaredConstructors(Class<?> c){
	      for (Constructor<?> constructor : c.getDeclaredConstructors()) {
	          System.out.println(constructor);
	      }
	  }

	  static void printAllConstructors(Class<?> c){
	      for (Constructor<?> constructor : c.getConstructors()) {
	          System.out.println(constructor);
	      }
	  }
}

এবং আমরা এই ফলাফল পাই:

getConstructors:
public com.codegym.Employee(java.lang.String,java.lang.String,int)
public.com.codegym.Employee()

getDeclaredConstructors:
ব্যক্তিগত com.codegym.Employee(java.lang.String,java.lang .স্ট্রিং)
পাবলিক com.codegym.Employee(java.lang.String,java.lang.String,int)
পাবলিক com.codegym.Employee()

ঠিক আছে, এইভাবে আমরা কনস্ট্রাক্টর অবজেক্টে অ্যাক্সেস পেতে পারি। এখন আমরা এটি কি করতে পারে তা নিয়ে কথা বলতে পারি।

java.lang.reflect.Constructor ক্লাস এবং এর সবচেয়ে গুরুত্বপূর্ণ পদ্ধতি

আসুন সবচেয়ে গুরুত্বপূর্ণ পদ্ধতিগুলি এবং সেগুলি কীভাবে কাজ করে তা দেখে নেওয়া যাক:

পদ্ধতি বর্ণনা
getName() একটি স্ট্রিং হিসাবে এই কনস্ট্রাক্টরের নাম প্রদান করে।
getModifiers() একটি সংখ্যা হিসাবে এনকোড করা জাভা অ্যাক্সেস মডিফায়ার ফেরত দেয়।
getExceptionTypes() ক্লাস অবজেক্টের একটি অ্যারে প্রদান করে যা কনস্ট্রাক্টর দ্বারা ঘোষিত ব্যতিক্রমগুলির প্রকারগুলিকে উপস্থাপন করে।
গেট প্যারামিটার() সমস্ত প্যারামিটারের প্রতিনিধিত্ব করে প্যারামিটার বস্তুর একটি অ্যারে প্রদান করে । কনস্ট্রাক্টরের কোনো প্যারামিটার না থাকলে দৈর্ঘ্য 0 এর একটি অ্যারে প্রদান করে।
getParameterTypes() ক্লাস অবজেক্টের একটি অ্যারে প্রদান করে যা ঘোষণা ক্রমে আনুষ্ঠানিক পরামিতি প্রকারগুলিকে উপস্থাপন করে।
getGenericParameterTypes() টাইপ অবজেক্টের একটি অ্যারে প্রদান করে যা ঘোষণার ক্রমে আনুষ্ঠানিক পরামিতি প্রকারের প্রতিনিধিত্ব করে।

getName() এবং getModifiers()

এর সাথে কাজ করা সুবিধাজনক করতে আমাদের অ্যারেকে একটি তালিকায় মোড়ানো যাক । আমরা getName এবং getModifiers পদ্ধতিগুলিও লিখব :

static List<Constructor<?>> getAllConstructors(Class<?> c) {
    return new ArrayList<>(Arrays.asList(c.getDeclaredConstructors()));
}

static List<String> getConstructorNames(List<Constructor<?>> constructors) {
    List<String> result = new ArrayList<>();
    for (Constructor<?> constructor : constructors) {
        result.add(constructor.toString());
    }
    return result;
}

static List<String> getConstructorModifiers(List<Constructor<?>> constructors) {
    List<String> result = new ArrayList<>();
    for (Constructor<?> constructor : constructors) {
        result.add(Modifier.toString(constructor.getModifiers()));
    }
    return result;
}

এবং আমাদের প্রধান পদ্ধতি, যেখানে আমরা সবকিছু কল করব:

public static void main(String[] args) {
    Class employeeClass = Employee.class;
    var constructors = getAllConstructors(employeeClass);
    var constructorNames = getConstructorNames(constructors);
    var constructorModifiers = getConstructorModifiers(constructors);

    System.out.println("Employee class:");
    System.out.println("Constructors :");
    System.out.println(constructorNames);
    System.out.println("Modifiers :");
    System.out.println(constructorModifiers);
}

এবং এখন আমরা আমাদের চাই সমস্ত তথ্য দেখতে পাই:

কর্মচারী শ্রেণী:
নির্মাণকারী:
[প্রাইভেট com.codegym.Employee(java.lang.String), পাবলিক
com.codegym.Employee(java.lang.String,java.lang.String,int), পাবলিক com.codegym.Employee() ]
সংশোধক:
[প্রাইভেট, পাবলিক, পাবলিক]

getExceptionTypes()

এই পদ্ধতিটি আমাদের কন্সট্রাক্টর নিক্ষেপ করতে পারে এমন ব্যতিক্রমগুলির একটি অ্যারে পেতে দেয়। আসুন আমাদের একটি কনস্ট্রাক্টরকে পরিবর্তন করি এবং একটি নতুন পদ্ধতি লিখি।

এখানে আমরা আমাদের বর্তমান কনস্ট্রাক্টরকে সামান্য পরিবর্তন করি:

private Employee(String name, String surname) throws Exception {
    this.name = name;
    this.lastName = lastName;
}

এবং এখানে ব্যতিক্রম প্রকারগুলি পাওয়ার জন্য আমাদের একটি পদ্ধতি রয়েছে এবং এটিকে প্রধানে যুক্ত করুন :

static List<Class<?>> getConstructorExceptionTypes(Constructor<?> c) {
      return new ArrayList<>(Arrays.asList(c.getExceptionTypes()));
}


var constructorExceptionTypes = getConstructorExceptionTypes(constructors.get(0));
System.out.println("Exception types :");
System.out.println(constructorExceptionTypes);

উপরে, আমরা আমাদের তালিকার প্রথম কনস্ট্রাক্টর অ্যাক্সেস করেছি। আমরা একটু পরে আলোচনা করব কিভাবে একটি নির্দিষ্ট কনস্ট্রাক্টর পেতে হয়।

এবং আমরা থ্রোস এক্সেপশন যোগ করার পরে আউটপুটটি দেখুন :

ব্যতিক্রম প্রকার:
[class java.lang.Exception]

এবং ব্যতিক্রম যোগ করার আগে:

ব্যতিক্রম প্রকার:
[]

সবকিছুই বিস্ময়কর, কিন্তু আমরা কীভাবে দেখতে পারি যে আমাদের কনস্ট্রাক্টরদের দ্বারা কী কী পরামিতি প্রয়োজন? এর পাশাপাশি এই চিন্তা করা যাক.

getParameters() & getParameterTypes() & getGenericParameterTypes()

আমাদের ব্যক্তিগত কনস্ট্রাক্টরকে পরিমার্জন করে আবার শুরু করা যাক। এখন এটি এই মত দেখাবে:

private Employee(String name, String surname, List<String> list) {
    this.name = name;
    this.lastName = lastName;
}

এবং আমাদের কাছে তিনটি অতিরিক্ত পদ্ধতি রয়েছে: প্যারামিটার এবং তাদের প্রকারের অর্ডার পাওয়ার জন্য getParameters , প্যারামিটারের প্রকারগুলি পাওয়ার জন্য getParameterTypes এবং জেনেরিকগুলিতে মোড়ানো প্রকারগুলি পাওয়ার জন্য getGenericParameterTypes

static List<Parameter> getConstructorParameters(Constructor<?> c) {
    return new ArrayList<>(Arrays.asList(c.getParameters()));
}

static List<Class<?>> getConstructorParameterTypes(Constructor<?> c) {
    return new ArrayList<>(Arrays.asList(c.getParameterTypes()));
}

static List<Type> getConstructorParametersGenerics(Constructor<?> c) {
    return new ArrayList<>(Arrays.asList(c.getGenericParameterTypes()));
}

এবং আমরা আমাদের ইতিমধ্যেই এত ছোট প্রধান পদ্ধতিতে আরও কিছু তথ্য যোগ করি:

var constructorParameterTypes = getConstructorParameterTypes(constructors.get(0));
var constructorParameters = getConstructorParameters(constructors.get(0));
var constructorParametersGenerics = getConstructorParametersGenerics(constructors.get(0));

System.out.println("Constructor parameters :");
System.out.println(constructorParameters);

System.out.println("Parameter types :");
System.out.println(constructorParameterTypes);

System.out.println("Constructor parameter types :");
System.out.println(constructorParametersGenerics);

আউটপুটের দিকে তাকিয়ে, আমরা আমাদের কনস্ট্রাক্টরগুলির পরামিতি সম্পর্কে খুব বিস্তারিত তথ্য দেখতে পাচ্ছি:

কনস্ট্রাক্টর প্যারামিটার:
[java.lang.String arg0, java.lang.String arg1, java.util.List<java.lang.String> arg2]
প্যারামিটারের ধরন:
[class java.lang.String, class java.lang.String, ইন্টারফেস java.util.List]
কনস্ট্রাক্টর প্যারামিটার প্রকার:
[class java.lang.String, class java.lang.String, java.util.List<java.lang.String>]

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

Constructor.newInstance() ব্যবহার করে একটি বস্তু তৈরি করা

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

আপনি যদি একটি একক কনস্ট্রাক্টর পেতে চান তবে আপনার getConstructor পদ্ধতি ব্যবহার করা উচিত ( getConstructors এর সাথে বিভ্রান্ত হবেন না , যা সমস্ত কনস্ট্রাক্টরের একটি অ্যারে প্রদান করে)। getConstructor পদ্ধতি ডিফল্ট কনস্ট্রাক্টর প্রদান করে

public static void main(String[] args) throws NoSuchMethodException {
    Class employeeClass = Employee.class;
    Constructor<?> employeeConstructor = employeeClass.getConstructor();
    System.out.println(employeeConstructor);
}
পাবলিক com.codegym.Employee()

এবং যদি আমরা একটি নির্দিষ্ট কনস্ট্রাক্টর পেতে চাই, আমাদের এই পদ্ধতিতে কনস্ট্রাক্টরের পরামিতি প্রকারগুলি পাস করতে হবে।

ভুলে যাবেন না যে আমরা getDeclaredConstructor পদ্ধতি ব্যবহার করে শুধুমাত্র আমাদের ব্যক্তিগত কনস্ট্রাক্টর পেতে পারি।

Constructor<?> employeeConstructor2 = employeeClass.getDeclaredConstructor(String.class, String.class, List.class);
System.out.println(employeeConstructor2);

এইভাবে আমরা একটি নির্দিষ্ট কনস্ট্রাক্টর পেতে পারি। এখন প্রাইভেট এবং পাবলিক কনস্ট্রাক্টর ব্যবহার করে অবজেক্ট তৈরি করার চেষ্টা করা যাক।

পাবলিক কনস্ট্রাক্টর:

Class employeeClass = Employee.class;
Constructor<?> employeeConstructor = employeeClass.getConstructor(String.class, String.class, int.class);
System.out.println(employeeConstructor);

Employee newInstance = (Employee) employeeConstructor.newInstance("Rob", "Stark", 10);
System.out.println(newInstance);

ফলাফল হল একটি বস্তু যা আমরা কাজ করতে পারি:

পাবলিক com.codegym.Employee(java.lang.String,java.lang.String,int)
কর্মচারী{name='Rob' surname='Stark', বয়স=10}

সবকিছু মহান কাজ করে! এখন আমরা একটি ব্যক্তিগত কনস্ট্রাক্টরের সাথে চেষ্টা করব:

Constructor<?> declaredConstructor = employeeClass.getDeclaredConstructor(String.class, String.class, List.class);
System.out.println(declaredConstructor);

Employee newInstance2 = (Employee) declaredConstructor.newInstance("Rob", "Stark", new ArrayList<>());
System.out.printf(newInstance2.toString());

ফলাফল আমাদের কনস্ট্রাক্টরের গোপনীয়তা সম্পর্কে একটি ত্রুটি:

জাভা এই কনস্ট্রাক্টর ব্যবহার করে একটি অবজেক্ট তৈরি করতে পারেনি, কিন্তু আসলে কিছু জাদু আছে যা আমরা মূল পদ্ধতিতে করতে পারি। আমরা আমাদের কনস্ট্রাক্টরের অ্যাক্সেস লেভেল করতে পারি, আমাদের ক্লাসের অবজেক্ট তৈরি করা সম্ভব করে তোলে:

declaredConstructor.setAccessible(true);

একটি বস্তু তৈরির ফলাফল

ব্যক্তিগত com.codegym.Employee(java.lang.String,java.lang.String,java.util.List)
কর্মচারী{name='Rob', surname='Stark', বয়স=-1}

আমরা আমাদের কনস্ট্রাক্টরে বয়স সেট করি না, তাই এটি যখন আরম্ভ করা হয়েছিল তখন একই থাকে।

বিস্ময়কর, এর যোগফল দেওয়া যাক!

Constructor.newInstance() ব্যবহার করে বস্তু তৈরির সুবিধা

উভয় পদ্ধতি একই নাম ভাগ করে, কিন্তু তাদের মধ্যে পার্থক্য আছে:

Class.newInstance() Constructor.newInstance()
শুধুমাত্র একটি নো-আর্গ কনস্ট্রাক্টর কল করতে পারেন। প্যারামিটারের সংখ্যা নির্বিশেষে যেকোনো কনস্ট্রাক্টরকে কল করতে পারে।
কনস্ট্রাক্টরকে দৃশ্যমান করতে হবে। নির্দিষ্ট পরিস্থিতিতে প্রাইভেট কনস্ট্রাক্টরদেরও কল করতে পারে।
কনস্ট্রাক্টর দ্বারা ঘোষিত কোনো ব্যতিক্রম (চেক করা বা না) নিক্ষেপ করে। InvocationTargetException দিয়ে সর্বদা একটি নিক্ষেপ করা ব্যতিক্রমকে মোড়ানো হয় ।

এই কারণে, Constructor.newInstance() কে Class.newInstance() এর চেয়ে পছন্দ করা হয় , এবং এটি বিভিন্ন ফ্রেমওয়ার্ক এবং API যেমন Spring, Guava, Zookeeper, Jackson, Servlet, ইত্যাদি দ্বারা ব্যবহৃত পদ্ধতি।