反射

1. 概念:

  • 反射主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
  • 反射机制的作用
    • 在运行时判断任意一个对象所属的类
    • 在运行时获取类的对象
    • 在运行时访问java对象的属性、方法、构造方法等
  • java.lang.reflect类库里面主要的类
    • Field 表示类中的成员变量
    • Method 表示类中的方法
    • Constructor 表示类的构造方法
    • Array 该类提供了动态创建数组和访问数组元素的静态方法
  • 反射依赖的Class 用来表示运行时类型信息的对应类
    • 每个类都有唯一一个与之相对应的Class对象
    • Class类为类类型,而Class对象为类类型对象
    • Class类的特点
      • Class类也是类的一种,class则是关键字
      • Class类只有一个私有的构造函数,只有JVM能够创建Class类的实例
      • JVM中只有唯一一个和类相对应的Class对象来描述其类型信息
    • 获取Class对象的三种方式
      • Object -> getClass()
      • 任何数据类型(包括基本数据类型)都有一个"静态"的class属性
      • 通过Class类的静态方法:forName(String className)(常用)
      • 在运行期间,一个类只有一个与之相对应的Class对象产生
    • Class对象就像一面镜子,透过这面镜子可以看到类的结构

2. 反射的主要用法

  • 如何获取类的构造方法并使用
/**
 * 通过Class对象可以获取某个类中的:构造方法
 *
 * 获取构造方法:
 *      1. 批量的方法
 *          public Constructor[] getConstructors() 所有"公有的"构造方法
 *          public Constructor[] getDeclaredConstructors() 获取所有的构造方法(包括私有 受保护 默认 公有)
 *      2. 获取单个的方法并调用
 *          public Constructor getConstructor(Class... parameterTypes) 获取单个的"公有的"构造方法
 *          public Constructor getDeclaredConstructor(Class... parameterTypes) 获取"某个构造方法"可以私有 受保护 默认 公有
 *
 *          调用构造方法:
 *          Constructor -> newInstance(Object... initargs)
 */
public class ConstructorCollector {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = Class.forName("demo.reflect.ReflectTarget");
        // 1. 获取所有的公有构造方法
        System.out.println("************************所有公有构造方法************************");
        Constructor[] conArray = clazz.getConstructors();
        for(Constructor c : conArray) {
            System.out.println(c);
        }
        // 2. 获取所有构造方法
        System.out.println("*********所有的构造方法(包括私有 受保护 默认 公有)*********");
        conArray = clazz.getDeclaredConstructors();
        for(Constructor c : conArray) {
            System.out.println(c);
        }
        // 3. 获取单个带参的公有方法
        System.out.println("*********获取公有、有两个参数的构造方法*********");
        Constructor con = clazz.getConstructor(String.class, int.class);
        System.out.println("con = " + con);
        // 4. 获取单个私有的构造方法
        System.out.println("*********获取私有构造方法*********");
        con = clazz.getDeclaredConstructor(int.class);
        System.out.println("private con = " + con);

        System.out.println("*********调用私有构造方法创建实例*********");
        // 暴力访问(忽略访问修饰符)
        con.setAccessible(true);
        ReflectTarget reflectTarget = (ReflectTarget) con.newInstance(1);
    }
}
public class ReflectTarget {
    //-----------构造函数-----------
    // (默认的带参构造函数)
    ReflectTarget(String str) {
        System.out.println("(默认)的构造方法s = " + str);
    }

    // 无参构造函数
    public ReflectTarget() {
        System.out.println("调用了公有的无参构造方法...");
    }

    // 有一个参数的构造函数
    public ReflectTarget(char name) {
        System.out.println("调用了带有一个参数的构造方法,参数值为 " + name);
    }

    // 有多个参数的构造函数
    public ReflectTarget(String name, int index) {
        System.out.println("调用了带有多个参数的构造方法,参数值为【目标名】: " + name + "【序号】" + index);
    }

    // 受保护的构造函数
    protected ReflectTarget(boolean n) {
        System.out.println("受保护的构造方法n:" + n);
    }

    // 私有的构造函数
    private ReflectTarget(int index) {
        System.out.println("私有的构造方法 序号:" + index);
    }
}

 

  • 如何获取类的成员变量并使用
/**
 * 获取成员变量并调用:
 *
 * 1. 批量的
 *      1). Field[] getFields() 获取所有的"公有字段"
 *      2). Field[] getDeclaredFields() 获取所有字段,包括私有 受保护 默认 公有
 * 2. 获取单个的
 *      1). public Field getField(String fieldName) 获取某个"公有的"字段
 *      2). public Field getDeclaredField(String fieldName) 获取某个字段(可以是私有的)
 *
 * 设置字段的值:
 *      Field -> public void set(Object obj, Object value)
 *      参数说明:
 *          1. obj:要设置的字段所在的对象
 *          2. value:要为字段设置的值
 */
public class FieldCollector {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 获取Class对象
        Class reflectTargetClass = Class.forName("demo.reflect.ReflectTarget");
        // 1. 获取所有公有的字段
        System.out.println("*********获取所有公有的字段*********");
        Field[] fieldArray = reflectTargetClass.getFields();
        for(Field f : fieldArray) {
            System.out.println(f);
        }
        // 2. 获取所有的字段
        System.out.println("*********获取所有的字段(包括私有 受保护 默认)*********");
        fieldArray = reflectTargetClass.getDeclaredFields();
        for(Field f : fieldArray) {
            System.out.println(f);
        }
        // 3. 获取单个特定公有的field
        System.out.println("*********获取公有字段并调用*********");
        Field f = reflectTargetClass.getField("name");
        System.out.println("公有的field name: " + f);
        ReflectTarget reflectTarget = (ReflectTarget) reflectTargetClass.getConstructor().newInstance();
        // 4. 给获取到的field赋值
        f.set(reflectTarget, "待反射一号");
        // 5. 验证对应的值name
        System.out.println("验证name:" + reflectTarget.name);
        // 6. 获取单个私有的Field
        System.out.println("*********获取私有字段targetInfo并调用*********");
        f = reflectTargetClass.getDeclaredField("targetInfo");
        f.setAccessible(true);
        System.out.println(f);
        f.set(reflectTarget, "13810592345");
        System.out.println("验证信息:" + reflectTarget);
    }
}
public class ReflectTarget extends ReflectTargetOrigin {
    //-----------构造函数-----------
    // (默认的带参构造函数)
    ReflectTarget(String str) {
        System.out.println("(默认)的构造方法s = " + str);
    }

    // 无参构造函数
    public ReflectTarget() {
        System.out.println("调用了公有的无参构造方法...");
    }

    // 有一个参数的构造函数
    public ReflectTarget(char name) {
        System.out.println("调用了带有一个参数的构造方法,参数值为 " + name);
    }

    // 有多个参数的构造函数
    public ReflectTarget(String name, int index) {
        System.out.println("调用了带有多个参数的构造方法,参数值为【目标名】: " + name + "【序号】" + index);
    }

    // 受保护的构造函数
    protected ReflectTarget(boolean n) {
        System.out.println("受保护的构造方法n:" + n);
    }

    // 私有的构造函数
    private ReflectTarget(int index) {
        System.out.println("私有的构造方法 序号:" + index);
    }

    //-----------字段-----------
    public String name;
    protected int index;
    char type;
    private String targetInfo;

    @Override
    public String toString() {
        return "ReflectTarget{" +
                "name='" + name + '\'' +
                ", index=" + index +
                ", type=" + type +
                ", targetInfo='" + targetInfo + '\'' +
                '}';
    }
}

 

public class ReflectTargetOrigin {
    String defaultMember = "default";
    public String publicMember = "public";
    protected String protectedMember = "protected";
    private String privateMember = "private";
}
  • 如何获取类的成员方法并使用
/**
 * 获取成员方法并调用
 * 1. 批量的
 *      public Method[] getMethods() 获取所有"公有方法";(包含了父类的方法也包含Object类)
 *      public Method[] getDeclaredMethods() 获取所有的成员方法,包括私有的(不包括继承的)
 * 2. 获取单个的
 *      public Method getMethod(String name, Class<?>... parameterTypes)
 *          参数:
 *              name:方法名
 *              Class...:形参的Class类型对象
 *      public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
 *
 * 调用方法:
 *  Method -> public Object invoke(Object obj, Object... args)
 *      参数说明:
 *      obj:要调用方法的对象
 *      args:调用方法时所传递的实参
 */
public class MethodCollector {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 1. 获取Class对象
        Class reflectTargetClass = Class.forName("demo.reflect.ReflectTarget");
        // 2. 获取所有公有方法
        System.out.println("**********获取所有的public方法,包括父类和Object**********");
        Method[] methodArray = reflectTargetClass.getMethods();
        for(Method m : methodArray) {
            System.out.println(m);
        }
        // 3. 获取该类的所有方法
        System.out.println("**********获取所有的方法,包括私有的**********");
        methodArray = reflectTargetClass.getDeclaredMethods();
        for (Method m : methodArray) {
            System.out.println(m);
        }
        // 4. 获取单个公有方法
        Method m = reflectTargetClass.getMethod("show1", String.class);
        System.out.println(m);
        // 5. 调用show1并执行
        ReflectTarget reflectTarget = (ReflectTarget) reflectTargetClass.getConstructor().newInstance();
        m.invoke(reflectTarget, "待反射方法一号");
        // 6. 获取一个私有的成员方法
        System.out.println("**********获取私有的show4()方法**********");
        m = reflectTargetClass.getDeclaredMethod("show4", int.class);
        System.out.println(m);
        m.setAccessible(true);
        String result = String.valueOf(m.invoke(reflectTarget, 20));
        System.out.println("返回值:" + result);
    }
}
public class ReflectTarget extends ReflectTargetOrigin {
    //-----------构造函数-----------
    // (默认的带参构造函数)
    ReflectTarget(String str) {
        System.out.println("(默认)的构造方法s = " + str);
    }

    // 无参构造函数
    public ReflectTarget() {
        System.out.println("调用了公有的无参构造方法...");
    }

    // 有一个参数的构造函数
    public ReflectTarget(char name) {
        System.out.println("调用了带有一个参数的构造方法,参数值为 " + name);
    }

    // 有多个参数的构造函数
    public ReflectTarget(String name, int index) {
        System.out.println("调用了带有多个参数的构造方法,参数值为【目标名】: " + name + "【序号】" + index);
    }

    // 受保护的构造函数
    protected ReflectTarget(boolean n) {
        System.out.println("受保护的构造方法n:" + n);
    }

    // 私有的构造函数
    private ReflectTarget(int index) {
        System.out.println("私有的构造方法 序号:" + index);
    }

    //-----------字段-----------
    public String name;
    protected int index;
    char type;
    private String targetInfo;

    @Override
    public String toString() {
        return "ReflectTarget{" +
                "name='" + name + '\'' +
                ", index=" + index +
                ", type=" + type +
                ", targetInfo='" + targetInfo + '\'' +
                '}';
    }

    //-----------成员方法-----------
    public void show1(String s) {
        System.out.println("调用了公有的,String参数的show1(): s = " + s);
    }
    protected void show2() {
        System.out.println("调用了受保护的,无参的show2()");
    }
    void show3() {
        System.out.println("调用了默认的,无参的show3()");
    }
    private String show4(int index) {
        System.out.println("调用了私有的,并且有返回值的,int参数的show4:index = " + index);
        return "show4result";
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值