java基础-反射

今天我们来说一说反射,首先,什么是反射?

java官方对反射的解释如下

反射允许对封装类的字段,方法,和构造函数的信息进行编程访问。

这句话就是说反射允许对成员变量成员方法构造方法的信息进行编程访问

java基础-反射_第1张图片

        图中我们可以发现,代码中有很多提示语句,这些提示语句都是通过反射实现的。利用反射可以获得所有方法、方法的形参并展示出来,这个就是反射。

        利用反射我们可以把成员变量获取出来,这时我们就可以获得这个成员变量的所有信息(修饰符、名字、数据类型、赋值/获取值)

        利用反射我们可以把构造方法获取出来,这时我们就可以获得这个构造方法的所有信息(修饰符、名字、形参、创建对象)

        利用反射我们可以把成员方法获取出来,这时我们就可以获得这个成员方法的所有信息(修饰符、名字、形参、返回值、抛出的异常、获取注解、运行方法)

利用反射我们就可以获取类里面的所有信息

综上我们可以将反射分为两类,获取和解剖

        在获取时,我们并不是从java中获取的,而是从class字节码文件中获取的,也就是java编译时产生的class文件,所以我们先学习如何获取class字节码文件的对象,再学习如何从字节码文件中获取字段、构造方法以及成员方法。一旦将其获取,我们就对他们进行解剖,获取里面的所有信息。

        如何获取class对象(三种方式)

1.Class.forName("全类名");

2.类名.class

3.对象.getClass();

java基础-反射_第2张图片

        对于java的运行过程,我们可以在源代码阶段应用第一种方式,在加载阶段应用第二种方式,在运行阶段应用第三种方式获取字节码文件。

首先,我们来演示第一种方式,建立一个student类,对其进行javabean的封装

package com.ittaotao.myreflect1;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

第一种方式Class.forName("全类名");

package com.ittaotao.myreflect1;

public class MyReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.获取student类的字节码文件对象
        //第一种方式
        //全类名:包名+类名 找到student类,选中student,右键copy reference,就可以获取其全类名
        //clazz就表示student类字节码文件的对象
        Class clazz = Class.forName("com.ittaotao.myreflect1.Student");

        System.out.println(clazz);
    }
}

运行结果

第二种方式 类名.class

//第二种方式
        Class clazz2 = Student.class; 

第三种方式 对象.getclass()

//第三种方式
        Student student = new Student();
        Class class3 = student.getClass();

        最后我们来总结一下三种方式的使用环境,一般来说第一种是比较常用的,第二种一般更多的是作为参数进行传递,第三种是当我们已经有了这个类的对象的时候才可以使用。

        综上,我们已经通过三种方式获取了字节码文件的对象,接下来我们就要通过反射来获取对应的成员变量、构造方法以及成员方法

        在java中,我们有一个定义,即万物皆对象。对应上方Constructor就是构造方法的对象,Field就是成员变量的对象,第三个Method就是成员方法的对象。

首先,我们要来学习通过反射获取构造方法

java基础-反射_第3张图片

这些方法全部存在于class类当中

接下来进行代码实现

首先,依旧是封装一个student的javabean类

package com.ittaotao.myreflect2;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name) {
        this.name = name;
    }

    protected Student(int age) {
        this.age = age;
    }

    private Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

接下来,利用反射获取构造方法(公共的和连同私有一起获取的)

package com.ittaotao.myreflect2;

import java.lang.reflect.Constructor;

public class MyReflectDemo2 {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.构造方法是在字节码文件中,所以需要获取class字节码文件
        Class clazz = Class.forName("com.ittaotao.myreflect2.Student");
        //2.获取构造方法
        //该方法只能获得公共的构造方法(public)
        Constructor[] cons = clazz.getConstructors();
        //3.遍历数组
        for (Constructor con :cons){
            System.out.println(con);
        }
        System.out.println("-------------------------");
        //连同私有方法一起获取
        Constructor[] cons2 = clazz.getDeclaredConstructors();
        for (Constructor con1 : cons2) {
            System.out.println(con1);
        }

    }
}

运行结果如下

java基础-反射_第4张图片

获取单个方法

//获取单个方法,不加s即可
        Constructor cons3 = clazz.getConstructor();
        System.out.println(cons3);

        System.out.println("----------------------------");

        //获取name的构造方法
        Constructor cons4 = clazz.getDeclaredConstructor(String.class);
        System.out.println(cons4);

        System.out.println("-----------------------------");

        //获取protected声明的构造方法
        Constructor cons5 = clazz.getDeclaredConstructor(int.class);
        System.out.println(cons5);

        System.out.println("-----------------------------");

        //获取两个参数的构造方法
        Constructor cons6 = clazz.getDeclaredConstructor(String.class, int.class);
        System.out.println(cons6);

运行结果

java基础-反射_第5张图片

接下来我们简单的介绍一下创建对象

//getDeclaredConstructor只能获取私有声明的构造方法,但不能创建对象,因此使用下面这句代码表示临时取消权限校验
        cons6.setAccessible(true);
        Student student = (Student) cons6.newInstance("张三", 23);
        System.out.println(student);

        以上就是获取class对象,以及利用反射获取构造方法的说明了,构造方法我并没有罗列全,有的方法,各位小伙伴们也可以自己根据图片中的方法试一下!

如有问题还请各位评论区多多提出!

你可能感兴趣的:(java,开发语言)