Java Reflect - 利用反射创建对象

本文详细介绍了Java反射机制中如何通过Class对象创建对象,包括使用默认构造器和指定构造器创建实例。同时,讲解了获取构造方法的四种方法:getConstructors(), getDeclaredConstructors(), getConstructor()和getDeclaredConstructor()。这些知识点在框架开发和通用平台中有着广泛的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Class对象可以获得该类里的方法(由Method对象表示)、构造器(由Constructor对象表示)、Field(由 Field 对象表示),这 3个类都位于java.lang.reflect 包下,并实现了java.lang.reflect.Member 接口。程序可以通过Method 对象来执行对应的方法,通过Constructor对象来调用对应的构造器创建实例,能通过Field对象直接访问并修改对象的属性值。

通过反射来生成对象有如下两种方式。

  • 使用Class对象的newInstance()方法来创建该Class对象对应类的实例,这种方式要求该 Class 对象的对应类有默认构造器,而执行 newInstance()方法时实际上是利用默认构造器来创建该类的实例
  • 先使用 Class 对象获取指定的 Constructor 对象,再调用 Constructor 对象的newInstance()方法来创建该Class对象对应类的实例。通过这种方式可以选择使用指定的构造器来创建实例。

通过第一种方式来创建对象是比较常见的情形,因为在很多Java EE框架中都需要根据配置文件信息来创建Java对象,从配置文件读取的只是某个类的字符串类名,程序需要根据该字符串来创建对应的实例,就必须使用反射。

public class Person {
    //私有的成员变量
    private String name;
    //默认的
    int age;
    //公共的
    public String address;

    public Person() {
        super();
    }
    //没有用public修饰的构造方法
    Person(int age, String address) {
        super();
        this.age = age;
        this.address = address;
    }

    //私有的构造方法
    private Person(String name) {
        super();
        this.name = name;
        this.age = age;
    }
    //公共的构造方法
    public Person(String name, int age, String address) {
        super();
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public void show() {
        System.out.println("show");
    }

    public void method(String s) {
        System.out.println("method"+s);
    }

    public String getString(String s,int i) {
        return s+"....."+i;
    }

    public void function() {
        System.out.println("function");
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
    }
}

1. 利用默认构造器来创建对象

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {

        Class clazz = Class.forName("com.example.redislock.reflect.Person");

        // 使用默认的构造方法创建对象
        Object object = clazz.newInstance();

        // Person [name=null, age=0, address=null]
        if(object instanceof Person){
            Person person = (Person) object;
            System.out.println(person);
        }

    }
}

2. 使用带参构造器创建对象

如果不想利用默认构造器来创建Java对象,而想利用指定的构造器来创建Java对象,则需要利用Constructor对象,每个Constructor对应一个构造器。为了利用指定的构造器来创建Java对象,需要如下3个步骤。

(1)获取该类的Class对象。

(2)利用Class对象的getConstructor()方法来获取指定的构造器。

(3)调用Constructor的newInstance()方法来创建Java对象。

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        Class clazz = Class.forName("com.example.redislock.reflect.Person");

        // Constructor类,也是java.lang.reflect包下的类
        // 获取代用3个参数,类型分别为int和String的构造器
        Constructor constructor = clazz.getConstructor(String.class,int.class, String.class);
        
        // 使用带有3个参数的构造方法创建对象
        Object obj = constructor.newInstance("zhangsan", 18 , "安徽省");

        if(obj instanceof Person){
            Person person = (Person) obj;
            // Person [name=zhangsan, age=18, address=安徽省]
            System.out.println(person);
        }
    }
}

当调用Constructor对象的newInstance()方法时通常需要传入参数,因为调用Constructor的newInstance()方法实际上等于调用它对应的构造器,传给newInstance()方法的参数将作为对应构造器的参数。

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        Class c = Class.forName("com.example.redislock.reflect.Person");
        //获取无参构造函数
        Constructor con = c.getDeclaredConstructor();

        //通过无参Constructor对象创建Person类的新实例
        // T newInstance(Object... initargs)
        Object obj = con.newInstance();
        System.out.println(obj);

        //获取带参构造函数对象
        Constructor con1 = c.getDeclaredConstructor(String.class,int.class,String.class);
        //通过带参构造函数对象
        Object obj1 =  con1.newInstance("林青霞",23,"北京");
        System.out.println(obj1);

        //获取私有的带参构造函数
        Constructor con2 = c.getDeclaredConstructor(int.class,String.class);
        //通过带参构造函数创建对象
        //打破封装,暴力访问
        con2.setAccessible(true);
        Object o = con2.newInstance( 23,"安徽省");
        System.out.println(o);
    }
}

通常没有必要使用反射来创建该对象,毕竟通过反射创建对象时性能要稍低一些。实际上,只有当程序需要动态创建某个类的对象时才会考虑使用反射,通常在开发通用性比较广的框架、基础平台时可能会大量使用反射。

通过Class类对象获取对应类的构造方法的四种情况:
在这里插入图片描述

3. getConstructors() - 获取所有的公共构造方法

在这里插入图片描述

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        Class clazz = Class.forName("com.example.redislock.reflect.Person");
        
        // 获取所有的public修饰的构造方法
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
    }
}

在这里插入图片描述

4. getDeclaredConstructors() - 获取所有构造方法

在这里插入图片描述

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        Class clazz = Class.forName("com.example.redislock.reflect.Person");

        // 获取所有的构造方法
        Constructor[] constructors = clazz.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
    }
}

在这里插入图片描述

5. getConstructor(Class<?>… parameterTypes) - 获取指定公共构造方法

在这里插入图片描述

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        Class clazz = Class.forName("com.example.redislock.reflect.Person");
		
        // 获取指定公共构造方法
        Constructor constructor = clazz.getConstructor(String.class,int.class, String.class);
        System.out.println(constructor);
    }
}

在这里插入图片描述

6. getDeclaredConstructor(Class<?>… parameterTypes) - 获取指定构造方法

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        Class clazz = Class.forName("com.example.redislock.reflect.Person");

        // // 获取指定构造方法
        Constructor constructor = clazz.getDeclaredConstructor(int.class, String.class);
        System.out.println(constructor);
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我一直在流浪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值