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 +
                '}';
    }
}

यह हमारी कक्षा होगी - कई क्षेत्रों के साथ, पैरामीटर, गेटर्स और सेटर्स के साथ एक कन्स्ट्रक्टर, एक टूस्ट्रिंग () विधि, और प्रारंभिक ब्लॉक। अब दूसरे भाग की ओर बढ़ते हैं: परावर्तन का उपयोग करके एक वस्तु बनाना। पहला तरीका जिसे हम देखेंगे वह 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:
सार्वजनिक com.codegym.Employee(java.lang.String,java.lang.String,int)
public.com.codegym.Employee()

getDeclaredConstructors:
private com.codegym.Employee(java.lang.String,java.lang) .String)
सार्वजनिक com.codegym.Employee(java.lang.String,java.lang.String,int)
सार्वजनिक com.codegym.Employee()

ठीक है, इस तरह हम कंस्ट्रक्टर ऑब्जेक्ट तक पहुँच प्राप्त करते हैं। अब हम बात कर सकते हैं कि यह क्या कर सकता है।

Java.lang.reflect.Constructor क्लास और इसके सबसे महत्वपूर्ण तरीके

आइए सबसे महत्वपूर्ण तरीकों पर नज़र डालें और वे कैसे काम करते हैं:

तरीका विवरण
गेटनाम () इस कंस्ट्रक्टर का नाम एक स्ट्रिंग के रूप में लौटाता है।
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), public
com.codegym.Employee(java.lang.String,java.lang.String,int), public 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);

ऊपर, हमने अपनी सूची में पहले कंस्ट्रक्टर को एक्सेस किया। हम थोड़ी देर बाद चर्चा करेंगे कि विशिष्ट कंस्ट्रक्टर कैसे प्राप्त करें।

और थ्रो अपवाद जोड़ने के बाद आउटपुट देखें :

अपवाद प्रकार:
[कक्षा 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]
पैरामीटर प्रकार:
[वर्ग Java.lang.String, वर्ग Java.lang.String, इंटरफेस java.util.List]
कंस्ट्रक्टर पैरामीटर प्रकार:
[क्लास java.lang.String, क्लास java.lang.String, java.util.List<java.lang.String>]

यह स्पष्ट रूप से प्रत्येक विधि के बीच के अंतर को प्रदर्शित करता है। हम देखते हैं कि हमारे पास पैरामीटर प्रकार, लिपटे प्रकार, और सामान्य रूप से सब कुछ के बारे में जानकारी प्राप्त करने के लिए अलग-अलग विकल्प हैं। बहुत अच्छा! अब जब हम कंस्ट्रक्टर वर्ग से परिचित हो गए हैं, तो हम अपने लेख के मुख्य विषय पर लौट सकते हैं - ऑब्जेक्ट बनाना।

Constructor.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)
कर्मचारी {नाम='रोब' उपनाम='स्टार्क', उम्र=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)
कर्मचारी {नाम='रोब', उपनाम='स्टार्क', उम्र=-1}

हम अपने कन्स्ट्रक्टर में उम्र निर्धारित नहीं करते हैं, इसलिए यह वही रहता है जब इसे प्रारंभ किया गया था।

बहुत बढ़िया, चलिए संक्षेप करते हैं!

Constructor.newInstance() का उपयोग करके ऑब्जेक्ट बनाने के लाभ

दोनों विधियों का नाम समान है, लेकिन उनके बीच अंतर हैं:

Class.newInstance () कंस्ट्रक्टर.न्यूइंस्टेंस ()
केवल नो-एर्ग कन्स्ट्रक्टर को कॉल कर सकते हैं। मापदंडों की संख्या की परवाह किए बिना किसी भी कंस्ट्रक्टर को कॉल कर सकते हैं।
कन्स्ट्रक्टर को दिखने की आवश्यकता है। कुछ खास परिस्थितियों में प्राइवेट कंस्ट्रक्टर्स को भी बुला सकते हैं।
कन्स्ट्रक्टर द्वारा घोषित किसी भी अपवाद (चेक या नहीं) को फेंकता है। फेंके गए अपवाद को हमेशा InvocationTargetException के साथ लपेटता है ।

इन कारणों से, Constructor.newInstance() को Class.newInstance() से अधिक पसंद किया जाता है , और यह स्प्रिंग, अमरूद, ज़ूकीपर, जैक्सन, सर्वलेट इत्यादि जैसे विभिन्न ढांचे और एपीआई द्वारा उपयोग की जाने वाली विधि है।