简述

反射在Java是一个非常重要的概念,同时反射也是框架设计的灵魂,反射使用的条件是必须得到class字节码文件。

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

要解析一个类,首先我们就需要获得该类的字节码文件。

总之,反射就是把Java类中的各种成分映射一个个Java对象(也可以理解成反序列化)

流程图

简单验证

编写简单Student类

package 反射;
public class Student {
    private String name ;
    private String sex;
    private Integer age;
    private void print(){
        System.err.print("姓名:"+name+"\t"+"性别:"+sex+"\t"+"年龄:"+age+"\t");
    }
}

编写反射类

package 反射;

/**
 * @ author Seale
 * @ Description: 反射学习
 * @ QQ:1801157108
 * @ Date 2020/4/29 21:36
 */
public class Invoke {
    public static void main(String[] args) {
        //实例化对象

        Student student = new Student();
        Class stuClass = student.getClass(); //获取Class对象
        System.out.println("当前类"+stuClass.getName()); // 输出当前类的名称

        Class stuClass2 = Student.class;
        System.out.println("和第一个对象是否相同: "+ (stuClass == stuClass2)); // 判断和第一个Class对象是否相同

        try {
            Class stuClass3 = Class.forName("反射.Student");
            System.out.println("和第二个对象是否相同: "+ (stuClass3 == stuClass2)); //判断和第二个Class对象是否相同
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

注意

三种生成Class的方式,常用的是第三种,反射类可以以字符串方式进行传入,同时也可以通过常用的配置文件进行读取,同时也是编写框架时最为常用的方式。

通过反射获取构造方法并且使用

改进Student类

package 反射;

/**
 * @ author Seale
 * @ Description: 反射理解
 * @ QQ:1801157108
 * @ Date 2020/4/29 21:33
 */

public class Student {
    private String name ;
    private String sex;
    private Integer age;
    private void print(){
        System.err.print("姓名:"+name+"\t"+"性别:"+sex+"\t"+"年龄:"+age+"\t");
    }

    public Student() {
        //无参构造方法
        System.out.println("公共无参构造方法被调用......");
    }
    protected Student(Boolean isTrue){
        System.out.println("受保护的构造方法是否被调用:"+(isTrue?"是":"不是"));
    }
    public Student(boolean isTrue){
        System.out.println("公有的构造方法是否被调用:"+(isTrue?"是":"不是"));
    }
    public Student(String name, String sex, Integer age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
        print();
    }

}

编写测试类

package 反射;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @ author Seale
 * @ Description:反射构造
 * @ QQ:1801157108
 * @ Date 2020/4/29 21:51
 */
public class ConstructorsTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = Class.forName("反射.Student");

        System.out.println("------------所有公共构造------------");
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor c : constructors) System.out.println(c);
        System.out.println("----------------------------------");

        //**********************************************************-
        System.out.println("------------所有构造(包括私有/默认/公有/受保护)------------");
        constructors = clazz.getDeclaredConstructors();
        for (Constructor c : constructors) System.out.println(c);
        System.out.println("------------------------------------------------------");

        //**********************************************************-
        System.out.println("------------获取参数是bool类型的公有构造------------");
        //获取私有等受保护的前面加上Declared即可
        Constructor con = clazz.getConstructor(boolean.class);
        System.out.println(con);
        //调用方法
        Object o = con.newInstance(true);
        System.out.println("---------------------------------------------");

    }

}
------------所有公共构造------------
public 反射.Student(boolean)
public 反射.Student(java.lang.String,java.lang.String,java.lang.Integer)
public 反射.Student()
----------------------------------
------------所有构造(包括私有/默认/公有/受保护)------------
public 反射.Student(boolean)
public 反射.Student(java.lang.String,java.lang.String,java.lang.Integer)
public 反射.Student()
protected 反射.Student(java.lang.Boolean)
------------------------------------------------------
------------获取参数是bool类型的公有构造------------
public 反射.Student(boolean)
公有的构造方法是否被调用:是
---------------------------------------------

获取成员变量

package 反射;

import java.lang.reflect.Field;

/**
 * @ author Seale
 * @ Description: 属性
 * @ QQ:1801157108
 * @ Date 2020/4/29 22:19
 */
public class Fields {
    public static void main(String[] args) throws Exception{
        //获取Class对象
        Class clazz = Class.forName("反射.Student");
        System.out.println("----------------所有的字段(包括受保护)---------------");
        Field[] fields = clazz.getDeclaredFields();
        for (Field f : fields)System.out.println(f);
        System.out.println("-------------------------------------------------");
        System.out.println();System.out.println();
        System.out.println("---------------------获取特定属性------------------");
        Field stu_name = clazz.getDeclaredField("name");
        System.out.println("当前获取的属性名称:\t"+stu_name);
        Field stu_sex = clazz.getDeclaredField("sex");
        //获取一个对象
        Object obj = clazz.getConstructor().newInstance();
        //属性设置
        stu_name.setAccessible(true); //暴力赋值 , 解除私有限制
        stu_sex.setAccessible(true);
        stu_name.set(obj,"反射给定的姓名");
        stu_sex.set(obj,"男");
        System.out.println("姓名:\t"+((Student) obj).getName());
        System.out.println("性别:\t"+((Student) obj).getSex());
        System.out.println("-------------------------------------------------");
    }
}
----------------所有的字段(包括受保护)---------------
private java.lang.String 反射.Student.name
private java.lang.String 反射.Student.sex
private java.lang.Integer 反射.Student.age
-------------------------------------------------

---------------------获取特定属性------------------
当前获取的属性名称:  private java.lang.String 反射.Student.name
公共无参构造方法被调用......
姓名: 反射给定的姓名
性别: 男
-------------------------------------------------

获得成员方法

修改Student

private void print1(){
        System.out.println("print1->私有");
    }
    protected void print2(){
        System.out.println("print2 -> 受保护");
    }
    public  void print3(){
        System.out.println("print3 -> 公有");
    }

编写测试

package 反射;

import java.lang.reflect.Method;

/**
 * @ author Seale
 * @ Description: 反射成员方法
 * @ QQ:1801157108
 * @ Date 2020/4/29 22:58
 */
public class MethodsClass {

    public static void main(String[] args) throws Exception{
        Class clazz = Class.forName("反射.Student");
        //获取公有方法
        System.out.println("-----------获取所有的公有方法---------");
        Method[] methods = clazz.getMethods();
        for (Method m : methods) System.out.println(m);
        System.out.println("-----------------------------------");

        System.err.println("--------------获取所有方法------------");
        methods = clazz.getDeclaredMethods();
        for (Method m : methods) System.err.println(m);
        System.err.println("------------------------------------");

        System.out.println("--------------获取特定方法------------");
        Method print1 = clazz.getDeclaredMethod("print1");
        System.out.println(print1);
        Object obj = clazz.getConstructor().newInstance();
        print1.setAccessible(true); //放开私有限制
        print1.invoke(obj); //调用方法
        System.out.println("------------------------------------");

    }

}
-----------获取所有的公有方法---------
public java.lang.String 反射.Student.getName()
public void 反射.Student.print3()
public java.lang.String 反射.Student.getSex()
public java.lang.Integer 反射.Student.getAge()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
-----------------------------------
--------------获取特定方法------------
private void 反射.Student.print1()
公共无参构造方法被调用......
print1->私有
------------------------------------
--------------获取所有方法------------
public java.lang.String 反射.Student.getName()
private void 反射.Student.print()
public void 反射.Student.print3()
public java.lang.String 反射.Student.getSex()
public java.lang.Integer 反射.Student.getAge()
protected void 反射.Student.print2()
private void 反射.Student.print1()
------------------------------------

Process finished with exit code 0

获取Main并且执行

public class MainClasses {
    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName("反射.Student");
        Method main_Method = clazz.getMethod("main", String[].class);
        main_Method.invoke(null, (Object) new String[]{});
    }
}
main被执行了!!!

本作品采用知识共享署名 4.0 国际许可协议进行许可。

如果可以的话,请给我钱请给我点赞赏,小小心意即可!

Last modification:April 29, 2020
If you think my article is useful to you, please feel free to appreciate