反射基础应用

什么是反射?

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

字节码文件和字节码文件对象

java文件:就是我们自己编写的java代码。
字节码文件:就是通过java文件编译之后的class文件(是在硬盘上真实存在的,用眼睛能看到的)
字节码文件对象:当class文件加载到内存之后,虚拟机自动创建出来的对象。
这个对象里面至少包含了:构造方法,成员变量,成员方法。
而我们的反射获取的是什么?字节码文件对象,这个对象在内存中是唯一的。

获取字节码文件对象的三种方式

最常用的是第一种通过全类名获取

通过字节码文件对象获取构造方法

其中构造方法的私有对应不同的方法。详情如下:

实例化对象

其中对私有构造方法形参的设置需要修改私有构造方法的访问权限,设置方法为setAccessible(true)。

获取成员变量

不同访问权限的成员变量对应不同的方法,详情如下:

成员变量的赋值与获取

如果要访问私有的成员变量就得修改访问权限。

获取成员方法

成员方法的执行

完整代码如下:

package com.tians.annotation;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @date : 2024/1/15 9:57
 */

public class MyTestMethodDemo {
    public static void main(String[] args) throws Exception {
        // 获取字节码文件对象(三种方式)
        Class<?> aClass = getClassObject();

        // 获取空参构造
        Constructor<?> constructor = aClass.getConstructor();
        System.out.println(constructor);
        // 获取全参构造
        Constructor<?> constructors = aClass.getConstructor(String.class, Integer.class);
        System.out.println(constructors);
        // 获取指定构造
        Constructor<?> constructor1 = aClass.getDeclaredConstructor(String.class);  //因为这个构造方法是私有的
        System.out.println(constructor1);
        Constructor<?> constructor2 = aClass.getDeclaredConstructor(Integer.class); //因为这个构造方法是私有的
        System.out.println(constructor2);

        // 实例化对象
        MyTestMethod object = (MyTestMethod) aClass.newInstance(); // 通过字节码文件对象直接实例化对象

        MyTestMethod objectByVoid = (MyTestMethod) constructor.newInstance(); //通过空参构造直接实例化对象
        System.out.println(objectByVoid);
        MyTestMethod objectByAll = (MyTestMethod) constructors.newInstance("张三",18); // 通过全参构造直接实例化对象
        System.out.println(objectByAll+":"+objectByAll.toString());
        // 判断是否需要修改私有构造方法的访问权限:私有成员反射需要修改访问权限
        constructor1.setAccessible(true);
        MyTestMethod objectByPointName = (MyTestMethod) constructor1.newInstance("李四"); // 通过有参构造直接实例化对象
        System.out.println(objectByPointName+":"+objectByPointName.getName());
        constructor2.setAccessible(true);
        MyTestMethod objectByPointAge = (MyTestMethod) constructor2.newInstance(80); // 通过有参构造直接实例化对象
        System.out.println(objectByPointAge+":"+objectByPointAge.getAge());

        // 获取单个成员变量对象公有
        Field name = aClass.getField("name");
        // Field age = aClass.getField("age");
        System.out.println(name);
        // 获取单个成员变量对象公有+私有
        Field nameByDeclared = aClass.getDeclaredField("name");
        Field ageByDeclared = aClass.getDeclaredField("age");
        System.out.println(nameByDeclared+":"+ageByDeclared);
        // 获取全部成员变量公有
        Field[] fieldsByPublic = aClass.getFields();
        for (Field field : fieldsByPublic) {
            System.out.println(field);
        }
        // 获取全部成员变量公有+私有
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        // 成员变量赋值和获取
        nameByDeclared.set(object,"tians");
        ageByDeclared.setAccessible(true);
        ageByDeclared.set(object,999);
        System.out.println(nameByDeclared.get(object)+":"+ageByDeclared.get(object));


        // 获取指定public方法
        Method methodByPub = aClass.getMethod("method1");
        System.out.println("获取指定public方法"+methodByPub);
        // 获取指定private方法
        Method methodByPri = aClass.getDeclaredMethod("printString",String.class);
        System.out.println("获取指定private方法"+methodByPri);
        // 获取所有public方法
        Method[] methodByAllPub = aClass.getMethods();
        for (Method method : methodByAllPub) {

            System.out.println("获取所有public方法"+method);
        }
        // 获取所有方法public+private
        Method[] methodByAll = aClass.getDeclaredMethods();
        for (Method method : methodByAll) {
            System.out.println("获取所有方法public+private"+method);
        }

        // 获取方法并执行
        methodByPub.invoke(object);
        methodByPri.setAccessible(true);
        methodByPri.invoke(object,"2024年1月15日18:09:04");

        for (Method method : methodByAll) {
            // 反射设置每个方法的访问权限
            method.setAccessible(true);
            // 判断方法上是否有注解
            if (method.isAnnotationPresent(MyTest.class)) {
                method.invoke(object);
            }
        }
        //
    }

    /**
     * 获取字节码文件对象(三种方式)
     * @return
     * @throws Exception
     */
    private static Class<?> getClassObject() throws Exception {
        Class<?> aClass = Class.forName("com.tians.annotation.MyTestMethod");   // 全类名获取
        System.out.println(aClass);
        Class<MyTestMethod> aClassByClass = MyTestMethod.class;    // 通过class属性获取
        System.out.println(aClassByClass);
        Class<? extends MyTestMethod> aClassByObjectClass = new MyTestMethod().getClass();   // 通过对象的class属性获取
        System.out.println(aClassByObjectClass);
        return aClass;
    }
}

package com.tians.annotation;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @date : 2024/1/15 9:51
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyTestMethod {

    public String name;
    private Integer age;

    @Override
    public String toString() {
        return "MyTestMethod{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    private void printString(String str) {
        System.out.println(name+":"+age+":"+str);
    }

    public MyTestMethod(String name) {
        this.name = name;
    }
    private MyTestMethod(Integer age ) {
        this.age = age;
    }

    @MyTest
    public void method1 () {
        System.out.println("method1");
    }
    public void method2 () {
        System.out.println("method2");
    }
    @MyTest
    public void method3 () {
        System.out.println("method3");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值