java通过反射创建对象的两种方式

本文深入探讨Java反射机制,介绍如何通过Class和Constructor类的newInstance()方法创建对象,对比两种方法的适用场景,适用于只有一个默认构造函数或需要使用带参构造函数的情况。

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

我个人觉得我自己是个比较粗心的人,所以各位大佬发现有什么不对的地方还请留言告知
在java中,通过反射创建对象有两种方式

  1. 使用Class对象的newInstance()方法来创建对象;
    具体步骤是:
    1、获取类的Class对象(有三种方式可以获取,可以自行百度一下)
    2、通过调用所获取到的Class对象的newInstance()来获得对象,该方法会返回一个Object类型的对象,所以还需要强转一下;
    举个例子:
    新建一个Hog,里面定义一个方法getName()输出一句话,可以看到运行之后控制台输出了青青草原四个字,
package Lin;

public class Pig {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        //通过类.class的方式获取一个该类的Class实例
        Class hogClass = Hog.class;
        //通过调用newInstance()方法获取一个Hog的实例, 该方法会返回一个Object类型的对象并且会抛出两个异常,
        Hog hog = (Hog) hogClass.newInstance();
        hog.getName();
    }
}
class Hog {
    public void getName() {
        System.out.println("青青草原");
    }
}

在这里插入图片描述

把上面的代码再修改一下
修改后的代码在Hog类构造函数中添加了一句代码,输出一句话,然后运行代码,可以发现构造函数被调用了,说明在使用Class类的newInstance()方法获得一个类的实例时,依然会调用他的(默认)构造函数;

package Lin;

public class Pig {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        //通过类.class的方式获取一个该类的Class实例
        Class hogClass = Hog.class;
        //通过调用newInstance()方法获取一个Hog的实例, 该方法会返回一个Object类型的对象并且会抛出两个异常,
        Hog hog = (Hog) hogClass.newInstance();
        hog.getName();
    }
}
class Hog {
    public Hog() {
        System.out.println("无参构造函数");
    }
    public void getName() {
        System.out.println("青青草原");
    }
}

在这里插入图片描述

  1. 通过Constructor类的newInstance()方法获取
    具体步骤是
    1、获取一个类的一个Class实例;
    2、调用Class中的getConstructor()方法获得一个Constructor对象,
    3、调用Constructor的newInstance()方法获得一个类的实例;

    再举个例子,把上面的代码稍微改一下:
    Hog类中的代码不变,在主方法中通过getConstructor()方法获得一个Constructor类的实例,然后通过Constructor的newInstance()方法获得一个类的实例;

getConstructor(Class<?>… parameterTypes)方法中可以传递Class类型的参数(不知到Class…的可以把他理解成参数是Class类型的数组),通过传递的参数来获得Class对象所包含的类的指定的public构造方法(就是找指定的构造方法,因为一个类可以有好多个构造方法,当你的一个构造方法为public Hog(int a) 时, 那就可以传递int.class进去)想知道的就查相关api吧,

package Lin;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Pig {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //通过类.class的方式获取一个该类的Class实例
        Class hogClass = Hog.class;
        //调用Class类的getConstructor()获得一个指定的构造器(参数为空则获得默认的构造器)对象   注意 获得的构造器得是被public修饰的
        Constructor constructor = (Constructor) hogClass.getConstructor();
        //调用Constructor的newInstance()方法获取一个Hog实例(注意要强转)
        Hog hog = (Hog) constructor.newInstance();
        hog.getName();
    }
}
class Hog {
    public Hog() {
        System.out.println("无参构造函数");
    }
    public void getName() {
        System.out.println("青青草原");
    }
}

运行截图:
在这里插入图片描述
将上面的代码再进行修改一下
1.在Hog类中定义一个带参的构造函数,形参为String类型
2.在主方法中调用Class的getConstructor()方法并传递String.class进去(告诉方法我要找到一个参数 是String类型的构造函数)
3.调用Constructor的newInstance()方法并传递一个String类型的字符串进去(可以理解成就是传递构造函数的参数进去)
运行之后可以看到带参数的构造函数被调用了;

package Lin;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Pig {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //通过类.class的方式获取一个该类的Class实例
        Class hogClass = Hog.class;
        //调用Class类的getConstructor()获得一个参数为String类型的构造器对象
        Constructor constructor = (Constructor) hogClass.getConstructor(String.class);
        //调用Constructor的newInstance()方法获取一个Hog实例(传递一个String类型的参数)
        Hog hog = (Hog) constructor.newInstance("我是Constructor类调用的");
        hog.getName();
    }
}

class Hog {
    public Hog() {
        System.out.println("无参构造函数");
    }

    public Hog(String message) {
        System.out.println(message);
    }

    public void getName() {
        System.out.println("青青草原");
    }
}

在这里插入图片描述
两种方法的区别
第一种方法、通过Class的newInstance()方法只能使用默认的构造方法,换句话说就是使用此方法是不能通过带参的构造函数来生成一个类的实例;

第二种方法、通过Constructor的newInstance()方法可以使用默认的构造方法,也可以使用带参的构造方法来生成一个类的实例

在只有一个默认的构造函数(或不带参数的构造函数)时,使用第一种方法比较方便,如果要使用类中的其他构造方法那只能使用第二种方法了。

### Java 使用反射创建对象 #### 获取 `Class` 对象的方式Java中,可以通过多种方式获得表示类的 `Class` 对象。这包括但不限于使用类字面常量、调用静态方法 `Class.forName()` 和从现有对象上调用 `getClass()` 方法[^3]。 #### 创建对象的一般流程 为了利用反射创建对象实例,通常遵循如下模式: 1. **获取构造函数** 需要先得到目标类型的 `Constructor<?>[]` 数组或者特定参数列表对应的单个 `Constructor<T>` 实例。 2. **实例化对象** 调用所选构造器上的 `newInstance(Object... initargs)` 方法传递必要的初始化参数来构建新实体。 对于公有的或是受保护级别的构造器可以直接访问;而对于私有化的构造器则需调整其可访问权限后再行操作[^1]。 #### 示例代码展示 ##### 公共/保护级别构造器示例 下面是一个简单的例子展示了如何通过反射机制使用公开或受保护的构造器创建 `Student` 类的新实例: ```java import java.lang.reflect.Constructor; public class Student { private String name; public Student(String name){ this.name = name; } } // 假设这段逻辑位于另一个地方... try{ // 加载Student类定义至内存中 Class<?> studentClazz = Class.forName("path.to.Student"); // 查找带有一个字符串参数的公共构造器 Constructor<?> constructor = studentClazz.getConstructor(String.class); // 构建新的学生记录 Object newStudentInstance = constructor.newInstance("张三"); }catch(Exception e){ System.out.println(e.getMessage()); } ``` ##### 私有构造器示例 这里给出了一种情形下怎样借助于反射技术绕过默认的安全限制从而激活内部隐藏起来的构造过程: ```java import java.lang.reflect.Constructor; class SingletonExample { private static final SingletonExample INSTANCE = new SingletonExample(); private SingletonExample(){} public static SingletonExample getInstance(){ return INSTANCE; } } // 外部尝试非法制造单件模式破坏者... try{ Class<?> singletonClass = Class.forName("path.to.SingletonExample"); // 找到无参但是private修饰符限定的构造器 Constructor<?> cons = singletonClass.getDeclaredConstructor(); // 设置为可访问状态以便后续动作执行 cons.setAccessible(true); // 利用修改后的属性建立额外副本 Object illegalSingletonCopy = cons.newInstance(); }catch(Exception ex){ System.out.println(ex.getMessage()); } ``` 上述两个片段分别演示了针对不同可见度等级下的构造器进行反射式实例化的具体实现细节[^2]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值