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

java 专栏收录该内容
8 篇文章 0 订阅

我个人觉得我自己是个比较粗心的人,所以各位大佬发现有什么不对的地方还请留言告知
在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()方法可以使用默认的构造方法,也可以使用带参的构造方法来生成一个类的实例

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

  • 1
    点赞
  • 0
    评论
  • 21
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值