Java的反射机制


Java的反射机制

一、反射的定义

  Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

二、反射的使用

1.反射是通过什么实现的?

    反射是通过Class类的对象实现的。Class对象存储在堆中(jdk1.7)之前,我们获取一个类的对象时,是通过类的构造器去创建该类的对象。有的时候,当一个类的构造器声明为private时,我们就不能从该类的外部去调用该类的构造器去创建对象,这个时候我们就可以使用反射机制来获取该类中所有的属性和方法。

2.实现反射的步骤

    ① 获取当前类的Class对象。(共有三种方式)

      1). 通过 “类名.class”的方式
      2). 通过Class类中的forName(String name),参数表示类的全路径名。
      3). 通过该类 实例对象的getClass();

    ② 设置构造器的访问权限,获取当前类的构造函数

      使用setAccessible()设置构造器的访问权限。

      1).使用Class对象的getConstructor(Class …ParameterTypes), 该方法用来获取类中只声明为public的构造器。参数Class…Parameter Types表示该参数类型的Class对象。

      2).使用getDeclaredConstructor(Class…ParameterTypes) 该方法用来获取类中所有权限修饰符的构造器,(一次只能获取一个)。

      3).使用 getDeclaredConstructors()获取该类中所有的构造器,并将它们存储到一个数组中。

3.通过反射获取类中的方法

    ① 通过获取的构造器,使用newInstance()获取该类的对象

    ② 获取类中的方法,使用通过newInstance()获取的对象,让其调用getDeclaredMethod(String name),以及使用setAccessible()设置方法的访问权限。

    ③ 使用invoke(Object obj) 实现方法的调用

代码如下(示例):

public class TestDemo1 {
    // 将构造器设为私有的,就不能去new 对象了。这个时候,我们使用该类的对象,就要去使用反射机制。
    private TestDemo1(){

    }

    public void eat(){
        System.out.println("中午了,该吃饭了");
    }

    public static void main(String[] args){
        //1. 先获取当前类的Class对象。 通过 ① 类名.class;
        Class<TestDemo1> testDemo1Class = TestDemo1.class;
        //2. 通过当前类的Class对象 获取当前类的构造器
        try {
            // 获取当前类的 无参构造器
            Constructor<TestDemo1> declaredConstructor = testDemo1Class.getDeclaredConstructor();

            //3. 获取类的构造器,我们将类的构造器 设置会 可访问的。
            declaredConstructor.setAccessible(true);

            //4. 通过类的构造器,获取类的对象
            TestDemo1 testDemo1 = declaredConstructor.newInstance();

            //5. 获取该类中的方法
            Method eat = testDemo1Class.getDeclaredMethod("eat");

            //6. 将该方法设置会可访问的。(防止是声明为private的方法。)
            eat.setAccessible(true);

            //6. 调用eat方法,通过invoke(Object obj): 表示,调用当前对象的 eat方法。
            eat.invoke(testDemo1); 

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

4.通过反射获取类中的属性

    1. 在获取对象后,我们再通过该类的class对象去获取类中的属性
    使用 getDeclaredFiled();
       getFiled();
       getDeclaredFileds();
       getFileds();
       使用方法 同理 构造器。

    2. 获取类的属性后,我们将该属性 通过setAccessible(true) 设置为 可访问的。

    3. 再使用 我们通过反射获取的 属性 的 set(Object o, String name); 去设置属性值
    参数一: Object o : 指明修改 哪个类的该属性的值。
    参数二: 要修改的属性值。

    4. 最后通过 反射获取的 属性 的 get(Object o) 去获取属性的值。

代码如下(示例):

public class TestDemo2 {
    public static void main(String[] args) {
        //1.获取People类的Class对象
        Class<People> peopleClass = People.class;
        //2.获取People类的有参构造
        try {
            Constructor<People> string_name = peopleClass.getDeclaredConstructor(String.class);

            //3. 将构造器的权限 设置为可访问的。
            string_name.setAccessible(true);

            //4. 获取该类的对象
            Object o = string_name.newInstance("lisi");

            //5. 获取name属性
            Field name = peopleClass.getDeclaredField("name");

            //6. 将name属性 设置会 可访问的。
            name.setAccessible(true);

            //7. 修改name的值
            name.set(o,"zs");

            //8. 获取name的值
            System.out.println(name.get(o));

        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}


// 通过反射,将name修改为"zs", 调用有参构造生成对象。
class People{
    private String name;

    private People(){

    }

    private People(String name){
        this.name = name;
    }


}

在运行阶段,JVM会创建一个该类的Class对象。这个Class对象只存在一份。且该对象中包含这个类的所有信息。反射的本质是,拿到Class对象后,反向获取类的信息。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值