Conto nggawe obyek nggunakake Class.newInstance()

Mbayangno sampeyan ditugasake nggawe obyek nggunakake refleksi. Apa kita bakal miwiti?

Kita bakal miwiti kanthi nulis kode kanggo kelas sing pengin kita instantiate:


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

Iki bakal dadi kelas kita - kanthi sawetara lapangan, konstruktor kanthi paramèter, getter lan setter, metode toString () , lan blok inisialisasi. Saiki ayo pindhah menyang bagean kapindho: nggawe obyek nggunakake refleksi. Pendekatan pisanan sing bakal kita deleng bakal nggunakake 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());
    }
}

Banget! Ayo mbukak kode lan nonton umur sing bakal ditampilake. Nanging kita entuk kesalahan babagan konstruktor standar sing ilang. Pranyata cara iki mung ngidini kita nggawe obyek kanthi nggunakake konstruktor standar. Ayo nambah konstruktor standar kanggo kelas kita lan nyoba kode maneh.

Pesen kesalahan:

Kode konstruktor anyar


public Employee() { }

Sawise nambahake konstruktor, iki minangka output:

umure 1

apik tenan! Kita ngerti carane cara iki bisa digunakake. Saiki ayo goleki ing ngisor hood. Mbukak dokumentasi, kita weruh yen metode kita wis ora digunakake :

Uga bisa mbuwang InstantiationException lan IllegalAccessException . Patut, dokumentasi tabet sing kita nggunakake cara liyane kanggo nggawe obyek, yaiku Constructor.newInstance () . Ayo analisa kanthi rinci babagan cara kerja kelas Konstruktor .

metode getConstructors lan getDeclaredConstructors

Kanggo nggarap kelas Konstruktor , kita kudu entuk conto. Kita duwe rong cara kanggo iki: getConstructors lan getDeclaredConstructors .

Sing pisanan ngasilake array konstruktor umum, lan sing kapindho ngasilake array kabeh konstruktor kelas.

Ayo menehi kelas kita sawetara privasi, utawa luwih, ayo nggawe sawetara konstruktor pribadi kanggo nduduhake carane cara iki bisa.

Ayo nambah sawetara konstruktor pribadi:


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

Deleng kode kasebut, cathet yen salah sawijining konstruktor pribadi:

Ayo nyoba metode kita:


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);
	      }
	  }
}

Lan kita entuk asil iki:

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 .String)
public com.codegym.Employee(java.lang.String,java.lang.String,int)
public com.codegym.Employee()

Oke, iki carane entuk akses menyang obyek Konstruktor . Saiki kita bisa ngomong babagan apa sing bisa ditindakake.

Kelas java.lang.reflect.Constructor lan cara sing paling penting

Ayo goleki cara sing paling penting lan cara kerjane:

Metode Katrangan
njalukName() Ngasilake jeneng konstruktor iki minangka senar.
getModifiers() Ngasilake modifikasi akses Jawa sing dienkode minangka nomer.
getExceptionTypes() Ngasilake macem-macem obyek Kelas sing makili jinis pengecualian sing diumumake dening konstruktor.
getParameters() Ngasilake macem-macem obyek Parameter sing makili kabeh paramèter. Ngasilake array dawa 0 yen konstruktor ora duwe paramèter.
getParameterTypes() Ngasilake array obyek Kelas sing makili jinis parameter formal ing urutan deklarasi.
getGenericParameterTypes() Ngasilake macem-macem obyek Tipe sing makili jinis parameter formal ing urutan deklarasi.

getName() & getModifiers()

Ayo lebokake larik ing dhaptar supaya gampang digarap. Kita uga bakal nulis metode getName lan 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;
}

Lan cara utama kita , ing ngendi kita bakal nelpon kabeh:


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);
}

Lan saiki kita ndeleng kabeh informasi sing dikarepake:

Kelas karyawan:
Konstruktor :
[private com.codegym.Employee(java.lang.String), public
com.codegym.Employee(java.lang.String,java.lang.String,int), public com.codegym.Employee() ]
Modifiers:
[pribadi, umum, umum]

getExceptionTypes()

Cara iki ngidini kita entuk macem-macem pengecualian sing bisa dilebokake konstruktor. Ayo ngowahi salah sawijining konstruktor lan nulis cara anyar.

Ing kene kita ngganti konstruktor saiki rada:


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

Lan ing kene kita duwe cara kanggo entuk jinis pangecualian lan ditambahake menyang utama :


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);

Ndhuwur, kita ngakses konstruktor pisanan ing dhaptar kita. Kita bakal ngrembug babagan carane njaluk konstruktor tartamtu mengko.

Lan katon ing output sawise kita nambah mbuwang Exception :

Jinis pangecualian :
[class java.lang.Exception]

Lan sadurunge nambah pangecualian:

Jinis pengecualian:
[]

Kabeh apik banget, nanging kepiye carane ndeleng paramèter apa sing dibutuhake konstruktor? Ayo ngerteni iki uga.

getParameters() & getParameterTypes() & getGenericParameterTypes()

Ayo miwiti maneh kanthi nyaring konstruktor pribadi. Saiki bakal katon kaya iki:


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

Lan kita duwe telung cara tambahan: getParameters kanggo njupuk urutan paramèter lan jinis, getParameterTypes kanggo njupuk jinis parameter, lan getGenericParameterTypes kanggo njupuk jinis sing dibungkus generik .


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()));
}

Lan kita nambah sawetara informasi liyane kanggo cara utama kita wis ora cilik :


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);

Nalika ndeleng output, kita ndeleng informasi sing rinci babagan paramèter konstruktor:

Parameter konstruktor :
[java.lang.String arg0, java.lang.String arg1, java.util.List<java.lang.String> arg2]
Tipe parameter :
[class java.lang.String, class java.lang.String, antarmuka java.util.List]
Tipe parameter konstruktor :
[class java.lang.String, class java.lang.String, java.util.List<java.lang.String>]

Iki kanthi jelas nuduhake bedane saben metode. Kita weruh manawa kita duwe pilihan sing kapisah kanggo entuk informasi babagan jinis parameter, jinis bungkus, lan kabeh umume. Super! Saiki kita wis kenal karo kelas Konstruktor , kita bisa bali menyang topik utama artikel kita - nggawe obyek.

Nggawe obyek nggunakake Constructor.newInstance()

Cara liya kanggo nggawe obyek yaiku nelpon metode newInstance ing konstruktor. Ayo goleki conto sing bisa digunakake lan deleng kepiye carane entuk konstruktor tartamtu.

Yen sampeyan pengin entuk konstruktor siji, sampeyan kudu nggunakake metode getConstructor (ora bakal bingung karo getConstructors , sing ngasilake array kabeh konstruktor). Cara getConstructor ngasilake konstruktor standar.


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

Lan yen kita pengin njaluk konstruktor tartamtu, kita kudu pass jinis parameter konstruktor kanggo cara iki.

Aja lali yen kita mung bisa njaluk konstruktor pribadi nggunakake metode getDeclaredConstructor .


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

Iki carane kita bisa njaluk konstruktor tartamtu. Saiki ayo nyoba nggawe obyek nggunakake konstruktor pribadi lan umum.

Konstruktor umum:


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);

Asil kasebut minangka obyek sing bisa digarap:

public com.codegym.Employee(java.lang.String,java.lang.String,int)
Karyawan{name='Rob' surname='Stark', age=10}

Kabeh kerjane apik! Saiki kita bakal nyoba karo konstruktor pribadi:


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());

Asilé yaiku kesalahan babagan privasi konstruktor kita:

Jawa ora bisa nggawe obyek nggunakake konstruktor iki, nanging ana soko gaib kita bisa nindakake ing cara utama . Kita bisa tingkat akses konstruktor, supaya bisa nggawe obyek kelas kita:


declaredConstructor.setAccessible(true);

Asil nggawe obyek

private com.codegym.Employee(java.lang.String,java.lang.String,java.util.List)
Karyawan{name='Rob', surname='Stark', age=-1}

Kita ora nyetel umur ing konstruktor kita, supaya tetep padha nalika diwiwiti.

Apik banget, ayo diringkes!

Keuntungan nggawe obyek nggunakake Constructor.newInstance ()

Kaloro cara kasebut duwe jeneng sing padha, nanging ana bedane:

Class.newInstance() Constructor.newInstance()
Mung bisa nelpon konstruktor no-arg . Bisa nelpon sembarang konstruktor preduli saka nomer paramèter.
Mbutuhake konstruktor katon. Bisa uga nelpon konstruktor pribadi ing kahanan tartamtu.
Mbuwang pangecualian (dicenthang utawa ora) sing diumumake dening konstruktor. Tansah mbungkus pengecualian sing dibuwang karo InvocationTargetException .

Kanggo alasan iki, Constructor.newInstance () disenengi saka Class.newInstance () , lan cara digunakake dening macem-macem frameworks lan API kayata Spring, Guava, Zookeeper, Jackson, Servlet, etc.