Java反射机制

1.反射定义:
Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。

2.反射作用:
取得任何一个已知名称的class的内部信息。

3.Class对象:
每个类都会产生一个对应的Class对象,也就是保存的.class文件。所有类都是在对其第一次使用时,动态加载到JVM的,当程序创建一个对类的静态成员的引用时,就会加载这个类。Class对象仅在需要的时候才会加载,static初始化是在类加载时进行的。

类加载器首先会检查这个类的Class对象是否已被加载过,如果尚未加载,默认的类加载器就会根据类名查找对应的.class文件。

想在运行时使用类型信息,必须通过Class对象获取,使用功能Class.forName(“对象名或者对象名.class”)。
注意:使用功能”.class”来创建Class对象的引用时,不会自动初始化该Class对象,使用forName()会自动初始化该Class对象。一个类在 JVM 中只会有一个 Class 实例

为了使用类而做的准备工作一般有以下3个步骤:
加载:由类加载器完成,找到对应的字节码,创建一个Class对象
链接:验证类中的字节码,为静态域分配空间
初始化:如果该类有超类,则对其初始化,执行静态初始化器和静态初始化块

4.方法
通过 Class 类获取成员变量、成员方法、接口、超类、构造方法等
查阅 API 可以看到 Class 有很多方法:
  getName():获得类的完整名字。
  getFields():获得类的public类型的属性。
  getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
  getMethods():获得类的public类型的方法。
  getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
  getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
  getConstructors():获得类的public类型的构造方法。
  getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
  newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
       invoke():打破封装。
5.例子

package com.test.reflect;

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

public class Test_Reflect {
    public  int age;
    private String name;
    private String sex;

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Test_Reflect(int age, String name, String sex) {
        super();
        this.age = age;
        this.name = name;
        this.sex = sex;
    }

    public Test_Reflect() {
        super();
    }

    public static void main(String[] args) throws Exception {
        Test_Reflect tr=new Test_Reflect();
        Class c = Class.forName("com.test.reflect.Test_Reflect");
        //Class c=tr.getClass();
        String className = c.getName();
        System.out.println(className);

        // 获得public属性
        Field[] fields = c.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }

        // 获得所有属性(包括私有)
        Field[] allFields = c.getDeclaredFields();
        for (Field field : allFields) {
            System.out.println(field.getName());
        }

        // 获得public方法,包括 Object 类的一些方法
        Method[] methods = c.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        
        // 获得所有方法
        Method[] allMethods = c.getDeclaredMethods();
        for (Method method : allMethods) {
            System.out.println(method.getName());
        }

        // 获得指定属性
        Field f1 = c.getField("age");
        System.out.println(f1);
        // 获得指定私有属性
        Field f2 = c.getDeclaredField("name");
        // 启用和禁用访问安全检查的开关,值为 true,则表示反射的对象在使用时应该取消 java 语言的访问检查;反之不取消
        f2.setAccessible(true);
        System.out.println(f2);

        // 创建类的对象
        Object p2 = c.newInstance();
        // 将 p2 对象的 f2 属性赋值为 Tom,f2 属性即为 私有属性 name
        f2.set(p2, "Tom");
        // 使用反射机制可以打破封装性,导致了java对象的属性不安全。
        System.out.println(f2.get(p2));

        // 获取构造方法
        Constructor[] constructors = c.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor.toString());
        }
    }
}

 

6.使用场景
JDBC原生代码注册驱动,hibernate 的实体类,Spring 的 AOP,逆向代码 ,例如反编译,与注解相结合的框架 例如Retrofit,单纯的反射机制应用框架 例如EventBus 2.x,动态生成类框架 例如Gson等

posted @ 2019-01-11 16:47  橘子洲头。  阅读(290)  评论(0编辑  收藏  举报