zoukankan      html  css  js  c++  java
  • Java 之反射机制

    java 语言的反射机制

    - 在运行状态中,对于任意一个类 (class 文件),都能够知道这个类的所有属性和方法;
    - 能动态获取类中的信息,也可以理解为对类(字节码文件)的解剖
    

    描述字节码文件的类

    与反射相关的三个对象

    - Constuctor : 将构造函数封装成对象
    - Field : 将字段封装成对象
    - Method : 将一般方法封装成对象
    

    获取字节码对象的三种方式

    1. Object 类中的 getClass() 方法

      • 想要用这种方式获取, 必须要明确具体的类, 并且需要创建对象
    2. 任何数据类型都具备一个静态的属性, 即通过.class来获取其对应的 Class 对象

      • 相对简单, 但是还是要明确用到类中的静态成员
    3. 只有通过给定的类的字符串名称就可以获取该类, 此方法更为扩展

      • 可以使用 Class 类中的 forName() 方法完成
      • 这种方式只要有名称即可, 更为方便, 扩展性更强

    获取 Class 中的构造函数

    // 早期: 使用 new 创建对象, 先根据被 new 的类的名称找寻该类的字节码文件, 并加载进内存,
    //      然后创建该字节码文件对象, 接着创建该字节码文件的对应的 Person 对象
        cn.itcast.bean.Person p = new cn.itcast.bean.Person();
    
    // 现在: 使用反射机制
        String name = "cn.itcast.bean.Person";
    
    // 找寻该名称对应的类文件, 并加载进内存, 产生 Class 对象
        Class clazz = Class.forName(name);
    // 如何产生该类的对象呢?  
        Object obj = clazz.newInstance();  // 调用空参的构造函数
    
    /*
     * 当获取指定名称对应类所体现的对象时,
     * 该类初始化不使用空参数构造函数该怎么办呢?
     * 构造函数带有了参数,就相当于指定了类中的某一个构造函数.
     * 既然通过指定的构造函数进行对象的初始化,
     * 所以应该先获取到该构造函数, 而这只需要通过字节码文件对象即可完成
     * 该方法有:
     *     getConstructors();  获取所有公共的构造函数
     *     getDeclaredConstructors();  获取所有构造函数.(包含公共, 保护, 默认访问和私有构造方法)
     *     getConstructor(Class<?>... parametreTypes);
     */
    
     // 获取指定的构造函数对象
    // 任何数据类型都具有一个静态的属性, .class, 获取 Class 对象
        Constructor constructor = clazz.getConstructor(String.class,int.class);
    
    // 通过该构造器对象 newInstance 方法进行对象的初始化
        Object obj = constructor.newInstance("张三",18);
    

    获取 Class 中的字段

        String name = "cn.itcast.bean.Person";
    
    // 找寻该名称对应的类文件, 并加载进内存, 产生 Class 对象
        Class clazz = Class.forName(name);
    
    // 获取相应的字段
        // Field field = clazz.getField("age");   只能获取公有的
        Field field = clazz.getdeclaredField("age"); // 只获取本类, 但包含私有
    
        // 对私有字段的方位取消权限检查, 暴力访问
            field.setAccessible(true);
    
    // 因为 Person p = new Person();
    //  设置 p 对象的年龄: p.age = 30;
    // 所以反射机制中获取(设置)字段的值,需要指定对象
        Object obj = clazz.newInstance();
    
        // 设置值
            field.set(obj,89);
        // 获取值
        Object o = field.get(obj);
    

    获取 Class 中的方法

    // 找寻该名称对应的类文件, 并加载进内存, 产生 Class 对象
        Class clazz = Class.forName( "cn.itcast.bean.Person");
    
        Method[] methods = clazz.getMethods();  // 获取的都是公有的方法
    
        methods = clazz.getDeclaredMethods();  // 只获取本类中所有方法, 包含私有
    
    // 获取指定名称的公有方法, 需要指定方法名称和参数列表
        Method method = clazz.getMethod("show", null);  // 获取空参数的一般方法
    
    // 创建对象
        Object obj = clazz.newInstance();
    
    // 一般方法的运行, 需要指定对象和参数列表
        method.invoke(obj,null);
    
    // 获取有参的一般方法
        Method method = clazz.getMethod("paramMethod", String.class, int.class);
    
    // 创建对象
        Object obj3 = clazz.newInstance();
    
    // 一般方法运行
        method.invoke(obj,"小强",24);
    

    **参考资料**
  • 相关阅读:
    JB开发之二 [jailbreak,越狱开发研究]
    iOS9 Https技术预研
    Tweak和app交互方案【进程通信】
    iOS设备抓包终极解决方案(支持https)
    Anti-Anti dylib(反 反-dylib钩子(Anti-tweak))
    Hook ptrace 调试加入了ptrace函数的程序
    How do I determine if I'm being run under the debugger?
    个人整理的一些iOS Entitlements
    SQLite在多线程环境下的应用
    别的程序员是怎么读你的简历的
  • 原文地址:https://www.cnblogs.com/linkworld/p/7523608.html
Copyright © 2011-2022 走看看