反射机制

作用

反射机制是一种操作字节码文件的方法
Spring等高级框架的底层实现都是通过反射机制。

想要操作字节码文件,首先要拿到这个字节码文件,如何获取字节码文件呢?

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

  1. Class.forName("")
    参数为类的全名称(不带后缀名)

forName("")这个方法会导致参数内的类加载,如果只想执行一个类中的静态代码块中的方法,可以直接使用Class.forName(""),因为静态代码块只在类加载的时候执行一次。

  1. 对象.getClass();
    每一个对象都有getClass()方法,用来获取该对象所属的类

  2. xx.Class
    任何一个类型都有.Class属性,代表其所属类。


Field ****反射机制较为重要的内容

通过反射机制获取到一个类后,下面再来获取这个类中的属性Field

User.java

public class User {
    public String name;
    protected String password;
    private int telphone;
    String emial;

    public void login(String name,String password){
    }

    public User() {
    }
    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }
}
public class Test01 {
    public static void main(String[] args) throws Exception{
        Class className = Class.forName("Reflect.User");
        Field[] fields = className.getFields();
        System.out.println(fields[0].getName());//---->name

        Field[] declaredFields = className.getDeclaredFields();
        for (Field field:declaredFields) {
            //获取修饰符
            String s1 = Modifier.toString(field.getModifiers());
            System.out.print(s1+'\t');
            //获取类型
            Class typeClass = field.getType();
            String simpleName = typeClass.getName();
            System.out.print(simpleName+'\t');
            //获取属性名
            System.out.println(field.getName());
        }

}

通过getFileds()获取属性,只能获取到public修饰的属性
通过getDeclaredFields()可以获取到所有属性
通过getDeclaredField(Object)可以获取到某一个Field属性对象,参数为该属性对应的Field对象的名字

public String name 属性名+类型+修饰符列表 表示一个Field对象,通过这个对象中的方法我们可以获取该对象里的内容

  1. 通过getName()获取名字name,
  2. 通过getType()获取类型所属的类java.lang.String,再通过String类的getSimpleName()方法获取其简类名String
  3. 通过getModifiers()获取访问控制权限代号1(int类型,public代号为1),再通过Modifier类的静态toString(int)方法,将代号转换为字符串,即可得到public

读写属性的值

在上面代码的情境下,获取到User类的名className 后,通过这个类名创建实例对象,

Class className = Class.forName("Reflect.User");
Object obj = className.newInstance();//这个obj就是User对象

Field field = className.getDeclearedField("name");
field.set(obj,"张三");  //设置name属性的值为张三
field.get(obj);        //获取到张三

这种方式无法访问私有属性
若想访问私有属性,可以通过Field对象的setAccessible()方法打破封装
这也是反射机制一个不安全的地方
field.setAccessible(true)


Method*****反射机制最重要的内容

通过反射机制调用方法

与获得属性对比,获得方法通过getDeclaredMethod() ,参数为方法名及其参数列表类型
eg:

Class className = Class.forName("Reflect.User");
Object obj = className.newInstance();

Method login = className.getDeclaredMethod("login",String.class,String.class);
login.invoke(obj,"张三","123456");//调用(invoke)login方法

Constructor

通过反射机制获取构造方法(getDeclaredConstructor)并创建对象(newInstance)

    Constructor con1 = className.getDeclaredConstructor();//获取无参构造
    Constructor con2 = className.getDeclaredConstructor(String.class, String.class);//两个参数的构造方法
    //调用构造方法创建对象
    con1.newInstance();
    con2.newInstance("李四","12312");

其他方法

  1. 获取类的父类:getSuperClass();
  2. 获取父接口:getInterfaces(); 返回一个Class[]
posted @ 2021-12-03 23:23  这个世界会好的  阅读(38)  评论(0编辑  收藏  举报