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:
सार्वजनिक 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() संख्या म्हणून एन्कोड केलेले Java प्रवेश सुधारक परत करते.
getExceptionTypes() कन्स्ट्रक्टरने घोषित केलेल्या अपवादांच्या प्रकारांचे प्रतिनिधित्व करणार्‍या क्लास ऑब्जेक्ट्सचा अॅरे मिळवते.
getParameters() सर्व पॅरामीटर्सचे प्रतिनिधित्व करणाऱ्या पॅरामीटर ऑब्जेक्ट्सचा अॅरे मिळवते . कन्स्ट्रक्टरकडे कोणतेही पॅरामीटर्स नसल्यास लांबी 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]
पॅरामीटर प्रकार:
[वर्ग java.lang.String, क्लास 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());

परिणाम म्हणजे आमच्या कन्स्ट्रक्टरच्या गोपनीयतेबद्दल त्रुटी:

Java हे कन्स्ट्रक्टर वापरून एखादी वस्तू तयार करू शकले नाही, परंतु मुख्य पद्धतीमध्ये आपण करू शकतो असे काहीतरी जादू आहे . आम्ही आमच्या कन्स्ट्रक्टरची ऍक्सेस लेव्हल करू शकतो, ज्यामुळे आमच्या क्लासच्या वस्तू तयार करणे शक्य होते:

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() पेक्षा प्राधान्य दिले जाते , आणि स्प्रिंग, Guava, Zookeeper, Jackson, Servlet इत्यादी विविध फ्रेमवर्क आणि API द्वारे वापरलेली पद्धत आहे.