Példa objektum létrehozására a Class.newInstance() használatával
Képzelje el, hogy Ön hozzá van rendelve egy objektum létrehozásához tükrözés segítségével. Kezdjük?
Kezdjük azzal, hogy megírjuk a példányosítani kívánt osztály kódját:
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 +
'}';
}
}
Ez lesz a mi osztályunk – több mezővel, egy konstruktorral, paraméterekkel, getterekkel és setterekkel, egy toString() metódussal és egy inicializálási blokkkal. Most térjünk át a második részre: objektum létrehozása reflexióval. Az első megközelítés, amelyet megvizsgálunk, a Class.newInstance() függvényt fogja használni .
public class Main {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
Employee employee = Employee.class.newInstance();
System.out.println("age is " + employee.getAge());
}
}
Kiváló! Futtassuk a kódunkat, és figyeljük, hogy megjelenik-e az életkor. De hibaüzenetet kapunk egy hiányzó alapértelmezett konstruktorról. Kiderült, hogy ezzel a módszerrel csak egy alapértelmezett konstruktor segítségével hozunk létre objektumot. Adjunk hozzá egy alapértelmezett konstruktort az osztályunkhoz, és teszteljük újra a kódot.
Hiba üzenet:

Az új kivitelező kódja
public Employee() { }
A konstruktor hozzáadása után itt a kimenet:
Nagy! Rájöttünk, hogyan működik ez a módszer. Most vessünk egy pillantást a motorháztető alá. A dokumentáció feltörésével azt látjuk, hogy a módszerünk már elavult :

Az InstantiationException és az IllegalAccessException parancsokat is el tudja dobni . Ennek megfelelően a dokumentáció azt javasolja, hogy az objektum létrehozásának másik módját használjuk, nevezetesen a Constructor.newInstance() . Elemezzük részletesen a Constructor osztály működését.
getConstructors és getDeclaredConstructors metódusok
A Constructor osztállyal való munkához először be kell szereznünk egy példányt. Két módszerünk van erre: getConstructors és getDeclaredConstructors .
Az első nyilvános konstruktorok tömbjét adja vissza, a második pedig az összes osztálykonstruktor tömbjét.
Adjunk egy kis magánéletet osztályunknak, vagy inkább hozzunk létre néhány privát konstruktort, amelyek segítenek bemutatni, hogyan működnek ezek a módszerek.
Adjunk hozzá néhány magánépítőt:
private Employee(String name, String surname) {
this.name = name;
this.lastName = lastName;
}
A kódot nézve vegye figyelembe, hogy az egyik konstruktor privát:

Teszteljük a módszereinket:
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);
}
}
}
És ezt az eredményt kapjuk:
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 .String)
public com.codegym.Employee(java.lang.String,java.lang.String,int)
public com.codegym.Employee()
Oké, így jutunk hozzá a Constructor objektumhoz. Most beszélhetünk arról, hogy mire képes.
A java.lang.reflect.Constructor osztály és legfontosabb metódusai
Nézzük meg a legfontosabb módszereket és azok működését:
Módszer | Leírás |
---|---|
getName() | Ennek a konstruktornak a nevét adja vissza karakterláncként. |
getModifiers() | Visszaadja a Java hozzáférés módosítókat számként kódolva. |
getExceptionTypes() | Osztály objektumok tömbjét adja vissza, amelyek a konstruktor által deklarált kivételtípusokat képviselik. |
getParameters() | Az összes paramétert reprezentáló Parameter objektumok tömbjét adja vissza . 0 hosszúságú tömböt ad vissza, ha a konstruktornak nincsenek paraméterei. |
getParameterTypes() | Osztály objektumok tömbjét adja vissza, amelyek deklarációs sorrendben reprezentálják a formális paramétertípusokat. |
getGenericParameterTypes() | A formális paramétertípusokat deklarációs sorrendben reprezentáló Type objektumok tömbjét adja vissza. |
getName() és getModifiers()
Tekerjük a tömbünket egy listába , hogy kényelmesebb legyen vele dolgozni. A getName és a getModifiers metódusokat is írjuk :
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;
}
És a fő módszerünk, ahol mindent nevezünk:
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);
}
És most minden szükséges információt látunk:
Konstruktorok :
[private com.codegym.Employee(java.lang.String), public
com.codegym.Employee(java.lang.String,java.lang.String,int), public com.codegym.Employee() ]
Módosítók :
[privát, nyilvános, nyilvános]
getExceptionTypes()
Ez a módszer lehetővé teszi, hogy megkapjuk a konstruktorunk által esetlegesen fellépő kivételek tömbjét. Módosítsuk az egyik konstruktorunkat, és írjunk egy új metódust.
Itt kicsit megváltoztatjuk jelenlegi konstruktorunkat:
private Employee(String name, String surname) throws Exception {
this.name = name;
this.lastName = lastName;
}
És itt van egy módszer a kivételtípusok lekérésére, és hozzáadjuk a főhöz :
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);
Fent elértük a listánk első konstruktorát. Kicsit később megbeszéljük, hogyan szerezzünk be egy konkrét konstruktőrt.
És nézze meg a kimenetet, miután hozzáadtuk a kivételeket :
[class java.lang.Exception]
És mielőtt hozzáadná a kivételt:
[]
Minden csodálatos, de hogyan látjuk, milyen paramétereket követelnek meg a kivitelezőink? Találjuk ki ezt is.
getParameters() & getParameterTypes() & getGenericParameterTypes()
Kezdjük újra a privát kivitelezőnk finomításával. Most így fog kinézni:
private Employee(String name, String surname, List<String> list) {
this.name = name;
this.lastName = lastName;
}
Három további módszerünk van: getParameters a paraméterek és típusaik sorrendjének lekéréséhez, getParameterTypes a paramétertípusok lekéréséhez, és getGenericParameterTypes a típusok generikusba csomagolt lekéréséhez .
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()));
}
És adunk még néhány információt a már nem is olyan kicsi fő módszerünkhöz:
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);
A kimenetet nézve nagyon részletes információkat látunk a konstruktoraink paramétereiről:
[java.lang.String arg0, java.lang.String arg1, java.util.List<java.lang.String> arg2]
Paramétertípusok :
[class java.lang.String, class java.lang.String, interfész java.util.List]
Konstruktor paramétertípusai :
[class java.lang.String, class java.lang.String, java.util.List<java.lang.String>]
Ez egyértelműen mutatja az egyes módszerek közötti különbséget. Azt látjuk, hogy külön lehetőségeink vannak a paramétertípusokról, a becsomagolt típusokról és általában mindenről információk beszerzésére. Szuper! Most, hogy megismertük a Constructor osztályt, visszatérhetünk cikkünk fő témájához – az objektumok létrehozásához.
Objektum létrehozása a Constructor.newInstance() segítségével
Az objektumok létrehozásának második módja a newInstance metódus meghívása a konstruktoron. Nézzünk meg egy működő példát, és nézzük meg, hogyan szerezhetünk be egy adott konstruktort.
Ha egyetlen konstruktort szeretne beszerezni, használja a getConstructor metódust (nem tévesztendő össze a getConstructors-szal , amely az összes konstruktor tömbjét adja vissza). A getConstructor metódus az alapértelmezett konstruktort adja vissza.
public static void main(String[] args) throws NoSuchMethodException {
Class employeeClass = Employee.class;
Constructor<?> employeeConstructor = employeeClass.getConstructor();
System.out.println(employeeConstructor);
}
Ha pedig konkrét konstruktort akarunk kapni, akkor ennek a metódusnak át kell adnunk a konstruktor paramétertípusait.
Ne felejtsük el, hogy privát konstruktorunkat csak a getDeclaredConstructor metódussal tudjuk megszerezni .
Constructor<?> employeeConstructor2 = employeeClass.getDeclaredConstructor(String.class, String.class, List.class);
System.out.println(employeeConstructor2);
Így kaphatunk egy konkrét konstruktort. Most próbáljunk meg objektumokat létrehozni privát és nyilvános konstruktorok használatával.
Nyilvános kivitelező:
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);
Az eredmény egy objektum, amellyel dolgozhatunk:
Alkalmazott{name='Rob' surname='Stark', age=10}
Minden remekül működik! Most megpróbáljuk egy privát kivitelezővel:
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());
Az eredmény egy hiba a konstruktorunk adatvédelmével kapcsolatban:

A Java nem tudott objektumot létrehozni ezzel a konstruktorral, de valójában van valami varázslatos, amit tehetünk a fő metódusban. A konstruktorunk hozzáférési szintjét tudjuk elérni, lehetővé téve osztályunk objektumainak létrehozását:
declaredConstructor.setAccessible(true);
Egy objektum létrehozásának eredménye
Alkalmazott{name='Rob', vezetéknév='Stark', age=-1}
Nem állítjuk be az életkort a konstruktorunkban, így az ugyanaz marad, mint az inicializáláskor.
Csodálatos, összegezzük!
Az objektumok Constructor.newInstance() használatával történő létrehozásának előnyei
Mindkét módszernek ugyanaz a neve, de vannak különbségek közöttük:
Class.newInstance() | Constructor.newInstance() |
---|---|
Csak no-arg konstruktort lehet hívni . | Bármilyen konstruktort hívhat, függetlenül a paraméterek számától. |
Megköveteli, hogy a konstruktor látható legyen. | Bizonyos körülmények között magánépítőket is hívhat. |
Bármilyen kivételt dob (ellenőrzött vagy nem), amelyet a konstruktor deklarált. | A kidobott kivételeket mindig az InvocationTargetException elemre csomagolja . |
Ezen okok miatt a Constructor.newInstance() előnyben részesített a Class.newInstance() helyett , és ezt a módszert használják különböző keretrendszerek és API-k, például Spring, Guava, Zookeeper, Jackson, Servlet stb.
GO TO FULL VERSION