Java基础-反射

反射的基本作用、关键?

  • 反射是在运行时获取类的字节码文件对象,然后可以解析类中的全部成分。
  • 反射的核心思想和关键就是:得到编译后的字节码(class)文件对象

反射的第一步:获取Class类对象,如此才可以解析类的全部成分

获取Class类的对象的三种方式

/**
 * 目标:反射第一步:获取class对象
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1. Class类中的一个静态方法:forName(全限定名:包名 + 类名)
        Class clz = Class.forName("per.mjn.reflect.Student");
        System.out.println(clz);

        // 2. 类名.class
        Class c1 = Student.class;
        System.out.println(c1);

        // 3. 对象.getClass()获取对象对应类的Class对象
        Student stu = new Student();
        Class c2 = stu.getClass();
        System.out.println(c2);
    }
}

 使用反射技术获取构造器对象并使用

  • 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。
  • Class类中用于获取构造器的方法
  1. Constructor<?>[] getConstructors()        返回所有构造器对象的数组(只能拿public的)
  2. Constructor<?>[] getDeclaredConstructors()    返回所有构造器对象的数组,存在就能拿到
  3. Constructor<?>[] getConstructor(Class<?>... parameterTypes)  返回单个构造器对象(只能拿public的)
  4. Constructor<?>[] getDeclaredConstructor(Class<?>... parameterTypes)  返回单个构造器对象,存在就能拿到
public class TestStudent01 {

    @Test
    public void getConstructors() {
        // a. 获取类对象
        Class c = Student.class;

        // b. 提取类中的全部构造器对象(只能拿public)
        Constructor[] constructors = c.getConstructors();

        // c. 遍历构造器
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "===>" + constructor.getParameterCount());
        }
    }

    @Test
    public void getDeclaredConstructors() {
        // a. 获取类对象
        Class c = Student.class;

        // b. 提取类中的全部构造器对象
        Constructor[] constructors = c.getDeclaredConstructors();

        // c. 遍历构造器
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "===>" + constructor.getParameterCount());
        }
    }

    @Test
    public void getConstructor() throws NoSuchMethodException {
        // a. 获取类对象
        Class c = Student.class;

        // b. 提取类中的单个构造器对象(按照参数定位无参数构造器,只能拿public修饰的构造器)
        Constructor constructor = c.getConstructor();

        System.out.println(constructor.getName() + "==>" + constructor.getParameterCount());
    }

    @Test
    public void getDeclaredConstructor() throws NoSuchMethodException {
        // a. 获取类对象
        Class c = Student.class;

        // b. 提取类中的单个构造器对象(按照参数定位无参数构造器)
        Constructor constructor = c.getDeclaredConstructor();

        System.out.println(constructor.getName() + "==>" + constructor.getParameterCount());


        // c. 定位某个有参构造器
        Constructor constructor1 = c.getDeclaredConstructor(String.class, int.class);
        System.out.println(constructor1.getName() + "==>" + constructor1.getParameterCount());
    }
}

使用反射技术获取构造器对象并使用

  • 获取构造器的作用依然是初始化一个对象返回。

Constructor类中用于创建对象的方法

  1. T newInstance(Object... initargs)       根据指定的构造器创建对象
  2. public void setAccessible(boolean flag)    设置为true,表示取消访问检查,进行暴力反射
public class TestStudentDemo2 {
    @Test
    public void getDeclaredConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // a. 获取类对象
        Class c = Student.class;

        // b. 提取类中的单个构造器对象(按照参数定位无参数构造器)
        Constructor constructor = c.getDeclaredConstructor();
        System.out.println(constructor.getName() + "==>" + constructor.getParameterCount());

        // 如果遇到了私有的构造器,可以暴力反射
        constructor.setAccessible(true);  // 权限被打开

        Student student = (Student) constructor.newInstance();
        System.out.println(student);

        // c. 定位某个有参构造器
        Constructor constructor1 = c.getDeclaredConstructor(String.class, int.class);
        System.out.println(constructor1.getName() + "==>" + constructor1.getParameterCount());

        Student student1 = (Student) constructor1.newInstance("孙悟空", 1000);
        System.out.println(student1);
    }
}
public class FieldDemo {

    /**
     * 获取全部成员变量
     */
    @Test
    public void getDeclaredFields() {
        // a. 定位Class对象
        Class c = Student.class;
        // b. 定位全部成员变量
        Field[] fields = c.getDeclaredFields();
        // c. 遍历一下
        for (Field field : fields) {
            System.out.println(field.getName() + "==>" + field.getType());
        }
    }

    /**
     * 获取某个成员变量
     */
    @Test
    public void getDeclaredField() throws NoSuchFieldException {
        // a. 定位Class对象
        Class c = Student.class;
        // b. 根据名称定位某个成员变量
        Field f = c.getDeclaredField("age");
        System.out.println(f.getName() + "==>" + f.getType());
    }
}

给通过反射得到的成员变量赋值

@Test
    public void getDeclaredField() throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // a. 定位Class对象
        Class c = Student.class;
        // b. 根据名称定位某个成员变量
        Field agef = c.getDeclaredField("age");
        agef.setAccessible(true);

        Constructor constructor = c.getDeclaredConstructor();

        // c. 赋值
        Student s = (Student) constructor.newInstance();
        agef.set(s, 18);
        System.out.println(s);

        // d. 取值
        int age = (int) agef.get(s);
        System.out.println(age);
    }

总结:

1、利用反射技术获取成员变量的方式

  • 获取类中成员变量对象的方法
  • getDeclaredFields()
  • getDeclaredField(String name)

2、反射得到成员变量可以做什么?

  • 依然是在某个对象中取值和赋值。
  • void set(Object obj, Object value)
  • Object get(Object obj)
  • 如果某成员变量是非public的,需要打开权限(暴力反射),然后再取值、赋值
  • setAccessible(boolean)

获取类中的全部成员方法对象

@Test
    public void getDeclaredMethods() {
        // a. 获取类对象
        Class c = Student.class;
        // b. 提取全部方法,包括私有的
        Method[] methods = c.getDeclaredMethods();
        // c. 遍历全部方法
        for (Method method : methods) {
            System.out.println(method.getName() + "返回值类型:" + method.getReturnType() + " 参数个数:" + method.getParameterCount());
        }
    }

通过反射调用方法

@Test
    public void getDeclaredMethod() throws Exception {
        // a. 获取类对象
        Class c = Student.class;
        // b. 提取单个方法对象
        Method m = c.getDeclaredMethod("setName", String.class);

        // 暴力打开权限
        m.setAccessible(true);

        // c. 触发方法执行
        Student student = new Student();
        // 注意:如果方法是没有结果回来的,那么返回的是null
        Object result = m.invoke(student, "dog");
        System.out.println(result);
    }

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

青衫客36

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

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

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

打赏作者

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

抵扣说明:

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

余额充值