Tạo instance của một class mà không gọi từ khóa new? (P1)

Như đã biết, trong Java để khởi tạo một instance của một class chúng ta sẽ sử dụng từ khóa new. Tuy nhiên, trong một số trường hợp chúng ta cần tạo một instance khi chỉ biết tên class hoặc private constructor hoặc không biết được số lượng tham số của constructor, … Với những trường hợp như vậy, chúng ta không thể gọi từ khóa new một cách trực tiếp mà sẽ sử dụng một số cách đặc biệt và chúng ta sẽ cùng tìm hiểu các cách giải quyết vấn đề này trong phần tiếp theo của bài viết.

Sử dụng Reflection khi biết tên class

Một trong những cách đơn giản và thường được sử dụng để tạo instance của một class là sử dụng kỹ thuật Reflection. Nếu bạn chưa biết về Reflection, hãy dành chút thời gian xem lại bài viết Hướng dẫn sử dụng Java Reflection.

Sử dụng newInstance() khi class có constructor không có tham số và phạm vi truy cập không phải private

package com.gpcoder.instance;
 
public class Employee {
 
    private int id;
 
    private String name;
 
    public Employee() {
        super();
    }
 
    public Employee(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + "]";
    }
}

Tạo instance sử dụng newInstance():

package com.gpcoder.instance;
 
import java.lang.reflect.InvocationTargetException;
 
public class NewInstanceExample {
 
    public static void main(String[] args)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException, NoSuchMethodException, SecurityException {
 
        // Get class based on the given class name
        Class<?> clazz = Class.forName("com.gpcoder.instance.Employee");
 
        // Create a new instance with empty argument of constructor of a class
        Employee employee = (Employee) clazz.newInstance();
        employee.setId(1);
        employee.setName("gpcoder");
        System.out.println("employee: " + employee);
    }
}

Lưu ý:

  • Nếu không tồn tại constructor không có tham số, chương trình sẽ throw ra một exception như sau:
Exception in thread "main" java.lang.InstantiationException: com.gpcoder.instance.Employee
    at java.lang.Class.newInstance(Class.java:427)
    at com.gpcoder.instance.NewInstanceExample.main(NewInstanceExample.java:15)
Caused by: java.lang.NoSuchMethodException: com.gpcoder.instance.Employee.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.newInstance(Class.java:412)
    ... 1 more

Sử dụng getConstructor() khi constructor của class là public

Chúng ta sẽ tạo instance của class Employee sử dụng phương thức getConstructor():

package com.gpcoder.instance;
 
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
 
public class ConstructorNewInstanceExample {
 
    public static void main(String[] args)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException, NoSuchMethodException, SecurityException {
 
        // Get class based on the given class name
        Class<?> clazz = Class.forName("com.gpcoder.instance.Employee");
 
        // Get all constructor of the class
        Constructor<?>[] allConstructors = clazz.getConstructors();
        for (Constructor<?> constructor : allConstructors) {
            Class<?>[] parameters = constructor.getParameterTypes();
            if (parameters.length == 0) {
                // Create a new instance without parameter
                Employee employee1 = (Employee) constructor.newInstance();
                employee1.setId(1);
                employee1.setName("gpcoder 1");
                System.out.println("employee1: " + employee1);
            } else if (parameters.length == 2) {
                // Create a new instance with two parameters
                Employee employee2 = (Employee) constructor.newInstance(2, "gpcoder 2");
                System.out.println("employee2: " + employee2);
            }
        }
         
        // Create a new instance with specific constructor of class
        Constructor<?> constructor = clazz.getConstructor(int.class, String.class);
        Employee employee3 = (Employee) constructor.newInstance(3, "gpcoder 3");
        System.out.println("employee3: " + employee3);
    }
}

Output của chương trình:

Sử dụng getDeclaredConstructor() khi constructor của class là private

package com.gpcoder.instance;
 
public class PrivateEmployee {
 
    private int id;
 
    private String name;
 
    private PrivateEmployee(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
 
    @Override
    public String toString() {
        return "PrivateEmployee [id=" + id + ", name=" + name + "]";
    }
}

Sử dụng getDeclaredConstructor() khi các constructor của class là private:

package com.gpcoder.instance;
 
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
 
public class PrivateConstructorNewInstanceExample {
 
    public static void main(String[] args)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException, NoSuchMethodException, SecurityException {
         
        // Get class based on the given class name
        Class<?> clazz = Class.forName("com.gpcoder.instance.PrivateEmployee");
         
        // Get the private constructor.
        Constructor<?> constructor = clazz.getDeclaredConstructor(int.class, String.class);
         
        // Since it is private, make it accessible.
        constructor.setAccessible(true);
 
        // Create a new instance with specific constructor of class
        PrivateEmployee employee = (PrivateEmployee) constructor.newInstance(1, "gpcoder");
        System.out.println("employee: " + employee);
    }
}

Output của chương trình:

employee: PrivateEmployee [id=1, name=gpcoder]

Tìm hiểu khoá học lập trình Web trong vòng 5 tháng!

Nguồn: https://gpcoder.com/5525-lam-the-nao-tao-instance-cua-mot-class-ma-khong-goi-tu-khoa-new/

Bài viết liên quan

Leave a Reply

Your email address will not be published.