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:
private 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() எண்ணாக குறியிடப்பட்ட ஜாவா அணுகல் மாற்றிகளை வழங்குகிறது.
விதிவிலக்கு வகைகள்() கன்ஸ்ட்ரக்டரால் அறிவிக்கப்பட்ட விதிவிலக்கு வகைகளைக் குறிக்கும் வகுப்புப் பொருள்களின் வரிசையை வழங்குகிறது.
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), public com.codegym.Employee() ]
மாற்றியமைப்பவர்கள் :
[தனியார், பொது, பொது]

விதிவிலக்கு வகைகள்()

இந்த முறையானது, எங்கள் கட்டமைப்பாளர் வீசக்கூடிய விதிவிலக்குகளின் வரிசையைப் பெற உதவுகிறது. எங்கள் கன்ஸ்ட்ரக்டர்களில் ஒருவரை மாற்றி புதிய முறையை எழுதுவோம்.

இங்கே நாம் நமது தற்போதைய கட்டமைப்பாளரை சிறிது மாற்றுகிறோம்:

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() ஐப் பயன்படுத்தி ஒரு பொருளை உருவாக்குதல்

பொருட்களை உருவாக்குவதற்கான இரண்டாவது வழி , கன்ஸ்ட்ரக்டரில் புதிய இன்ஸ்டன்ஸ் முறையை அழைப்பதாகும் . ஒரு வேலை செய்யும் உதாரணத்தைப் பார்த்து, ஒரு குறிப்பிட்ட கட்டமைப்பாளரைப் பெறுவது எப்படி என்பதைப் பார்ப்போம்.

நீங்கள் ஒரு ஒற்றை கன்ஸ்ட்ரக்டரைப் பெற விரும்பினால், நீங்கள் 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() Constructor.newInstance()
No-arg கன்ஸ்ட்ரக்டரை மட்டுமே அழைக்க முடியும் . அளவுருக்களின் எண்ணிக்கையைப் பொருட்படுத்தாமல் எந்த கட்டமைப்பாளரையும் அழைக்கலாம்.
கன்ஸ்ட்ரக்டர் தெரியும்படி இருக்க வேண்டும். சில சூழ்நிலைகளில் தனியார் கட்டமைப்பாளர்களையும் அழைக்கலாம்.
கன்ஸ்ட்ரக்டரால் அறிவிக்கப்படும் விதிவிலக்கை (சரிபார்த்ததோ இல்லையோ) வீசுகிறது. எப்பொழுதும் InvocationTargetException உடன் தூக்கி எறியப்பட்ட விதிவிலக்கை மூடுகிறது .

இந்தக் காரணங்களுக்காக, Class.newInstance () ஐ விட Constructor.newInstance() விரும்பப்படுகிறது , மேலும் இது Spring, Guava, Zookeeper, Jackson, Servlet போன்ற பல்வேறு கட்டமைப்புகள் மற்றும் APIகளால் பயன்படுத்தப்படும் முறையாகும்.