• TIII-Android技术篇之反射


    对于一个类来说,最重要的是什么?

    构造+属性+方法+访问权限
    
    待测试的类
    /**
     * 作者:张风捷特烈
     * 时间:2018/5/6:10:40
     * 邮箱:1981462002@qq.com
     * 说明:反射测试类
     */
    public class Person {
        private int age;
        private String name;
        private boolean isMan;
        public String address="beijing";
    
        public Person() {
            System.out.println("空参构造执行...");
        }
    
        public Person( String name, int age,boolean isMan) {
            this.age = age;
            this.name = name;
            this.isMan = isMan;
            System.out.println("三参构造执行...");
    
        }
    
        public void publicShow() {
            System.out.println("I am " + name + ",I " + age + "years");
        }
    
        public static void staticShow() {
            System.out.println("staticShow");
        }
    
    
        private void privateShow() {
            System.out.println("I am " + name + ",I " + age + "years");
        }
    
        public void paramShow(String str,int num) {
            System.out.println("I am " + str + ",I " + num + "years");
        }
    }
    

    一、拿到Class对象

    Class对象是什么?

    Class是一个类,而且它只有一个私有的构造函数,说明它不能通过new来获取对象,构造函数传入一个ClassLoader。
    每个类被加载进入内存之后,系统就会为该类生成一个对应的java.lang.Class对象,
    通过该Class对象就可以访问到JVM中的这个类,就可以获取某类的一切
    
    private Class(ClassLoader loader) {
        // Initialize final field for classLoader.  The initialization value of non-null
        // prevents future JIT optimizations from assuming this final field is null.
        classLoader = loader;
    }
    
    1.对象.getClass()获取Class对象

    前提:已存在对象,未知该类全貌,可以使用此方法获取Class对象来探测该类

    Object类中有一个native方法获取Class
    public final native Class<?> getClass();
    
        public static void getClass_1() {
            Person person = new Person();
            Class<? extends Person> personClass = person.getClass();
        }
    
    2.类名.class获取Class对象

    前提:需要已知类名

    public static void getClass_2() {
        Class<Person> personClass = Person.class;
    }
    
    3.通过指定字符串:获取Class对象

    前提:需已知全类名

    public static void getClass_3() {
        try {
            Class<?> person = Class.forName("top.toly.bean.Person");
         System.out.println(person);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    

    二、通过反射构造对象

    1.获取无参构造实例化对象:clazz.newInstance()
    /**
     * 通过反射建无参实例
     */
    public static void createInstance() {
        //早期:new 的时候,先根据类名寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
        // 再创建该字节码文件对相应的Person对象
        try {
            String className = "top.toly.bean.Person";
            // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
            Class<?> clazz = Class.forName(className);
            Object instance = clazz.newInstance();
            System.out.println(instance instanceof Person);//true
        } catch (Exception e) {
            e.printStackTrace();
        }
    
    2.通过反射建有参实例:clazz.getConstructor
     /**
      * 通过反射建有参实例
      */
     private static void createInstance_2() {
         try {
             String className = "top.toly.bean.Person";
             // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
             Class<?> clazz = Class.forName(className);
             Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class);
             Object instance = constructor.newInstance("捷特", 24, true);
             System.out.println(instance);
             //Person{age=24, name='捷特', isMan=true, address='beijing'}
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
    
    补充:XXXDeclaredXXX都是只获取本类,不包括父类
    // 获得该类所有的构造器,不包括其父类的构造器
    public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
    // 获得该类所以public构造器,包括父类 
    public Constructor<T> getConstructor(Class<?>... parameterTypes)
    

    三、通过反射获取字段

    1.获取公共字段:clazz.getField
    /**
     * 获取公共字段
     */
    public static void getPublicField() throws Exception {
        String className = "top.toly.bean.Person";
        // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
        Class<?> clazz = Class.forName(className);
        Field address = clazz.getField("address");//获取公有字段
        Object o = address.get(clazz.newInstance());
        System.out.println(o);//beijing
    }
    
    2.获取私有字段:
    /**
     * 获取私有字段
     */
    public static void getPrivateField() throws Exception {
        String className = "top.toly.bean.Person";
        // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
        Class<?> clazz = Class.forName(className);
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class);
        Object instance = constructor.newInstance("捷特", 24, true);
        //可以获取所有类型字段
        Field name = clazz.getDeclaredField("age");
        //想要访问私有,需要将可获取置为true
        name.setAccessible(true);
        //设置私有成员值
        name.setInt(instance,30);
        //获取私有成员值
        Object o = name.get(instance);
        System.out.println(o);//30
    }
    

    四、调用方法:

    1.获取公共方法:getMethods()
    /**
     * 获取公共方法
     */
    public static void getPublicMethod() throws Exception {
        String className = "top.toly.bean.Person";
        // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
        Class<?> clazz = Class.forName(className);
        //创建实例
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class);
        Object instance = constructor.newInstance("捷特", 24, true);
        Method[] methods = clazz.getMethods();//只能获取公有方法,包括父类
        for (Method m : methods) {
            System.out.println(m);
        }
        //获取公共无参
        Method publicShow = clazz.getMethod("publicShow", null);
        //调用函数:invoke
        publicShow.invoke(instance, null);
        //获取公共有参
        Method paramShow = clazz.getMethod("paramShow", String.class, int.class);
        paramShow.invoke(instance, "龙少", 24);
    }
    

    clazz.getDeclaredMethod:获取指定名称和参数类型的本类中声明(访问权限不限)的方法
    clazz.getDeclaredMethods(): 获取该类所有的方法,不包括父类
    clazz.getMethod:获取当前类及所有继承的父类的public修饰的方法。仅包括public
    clazz.getMethods();获取该类所有的public方法,包括父类的

    2.获取私有方法:getDeclaredMethods()
    /**
     * 获取私有方法
     */
    public static void getPrivateMethod() throws Exception {
        String className = "top.toly.bean.Person";
        // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
        Class<?> clazz = Class.forName(className);
        Method[] declaredMethods = clazz.getDeclaredMethods();//获取该类中的所有方法
        //创建实例
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class);
        Object instance = constructor.newInstance("捷特", 24, true);
        for (Method m : declaredMethods) {
            System.out.println(m);
        }
        Method privateShow = clazz.getDeclaredMethod("privateShow", null);
        privateShow.setAccessible(true);
        privateShow.invoke(instance,null);
    }
    

    反射差不多也就这些,理论并不难,学以致用才是关键


    后记、

    1.声明:

    [1]本文由张风捷特烈原创,转载请注明
    [2]欢迎广大编程爱好者共同交流
    [3]个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
    [4]你的喜欢与支持将是我最大的动力

    2.连接传送门:

    更多安卓技术欢迎访问:安卓技术栈
    我的github地址:欢迎star
    简书首发,腾讯云+社区同步更新
    张风捷特烈个人网站,编程笔记请访问:http://www.toly1994.com

    3.联系我

    QQ:1981462002
    邮箱:1981462002@qq.com
    微信:zdl1994328

    4.欢迎关注我的微信公众号,最新精彩文章,及时送达:
    9414344-c474349cd3bd4b82.jpg
    公众号.jpg
  • 相关阅读:
    异或(^/XOR)的研究
    FastJson的使用
    KindEditor使用
    Java之Collection一
    Java之String
    Github基本使用
    Ubuntu jekyll git使用小记
    使用html editor 打开freemarker文件
    struts.xml 标签顺序
    multipart/form-data ajax 提交问题(未解决)
  • 原文地址:https://www.cnblogs.com/toly-top/p/9781884.html
Copyright © 2020-2023  润新知