美文网首页
Android依赖注入之反射

Android依赖注入之反射

作者: Heweii | 来源:发表于2019-08-13 16:00 被阅读0次

    前言

    上一篇介绍了依赖注入中的注解,而且篇末还贴了一段通过反射操作注解的代码,传送门https://www.jianshu.com/p/9d20a7391057

    一.反射概念

    在运行状态中,能够获取到任意一个类的属性和方法,并且能够操作对应的属性和方法,我们把这种能动态操作对象属性和方法的方式称为Java反射机制。反射就是把java类中的每个成员映射成一个个的对象,我们就是要取出这些对象进行操作。

    要获取一个类的属性和方法,就得获取他的字节码class文件(.java文件编译后都会对应有一个.class文件)对应Class类型的对象,Class对象的由来就是将字节码class文件加载进内存并创建一个Class的对象。

    二.Class类

    1.Class类简介

    Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中每个类都有对应的Class对象。
    Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass方法自动构造的。

    2.Class对象获取

    三种方式获取:
    1.该类对象.getClass();
    2.该类(或数据类型).class;
    3.利用Class.forName(包名+类名),参数为该类的完整路径;
    最好用第三种,前两种方式依赖太强。

    package com.dzy.samefunctiondemo.fanshe;
    
    public class Programmer {
    }
    
    public class Reflect {
        public static void main(String[] args) {
            Programmer programmer = new Programmer();
            Class proClass1 = programmer.getClass();
            Class proClass2 = Programmer.class;
            try {
                Class proClass3 = Class.forName("com.dzy.samefunctiondemo.fanshe.Programmer");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    

    三.反射使用

    1.获取构造方法

    package com.dzy.samefunctiondemo.fanshe;
    
    public class Programmer {
    
        public Programmer(){
        }
    
        public Programmer(String name){
            System.out.println("Name:"+name);
        }
    
        private Programmer(int age){
            System.out.println("Age:"+age);
        }
    
        protected Programmer(double weight){
        }
    
    }
    
    public class Reflect {
        public static void main(String[] args) {
            try {
                Class proClass = Class.forName("com.dzy.samefunctiondemo.fanshe.Programmer");
    
                //获取所有构造方法
                Constructor[] constructors1 = proClass.getDeclaredConstructors();
    
                //获取所有公共(public)构造方法
                Constructor[] constructors2 = proClass.getConstructors();
    
                //获取某个带参数的构造方法
                Constructor constructor1 = proClass.getDeclaredConstructor(int.class);
                constructor1.setAccessible(true);//由于私有方法无访问权限,这个是直接开启访问权限
                constructor1.newInstance(50);//创建对应构造器的对象
    
                //获取某个带参数的公共构造方法
                Constructor constructor2 = proClass.getConstructor(String.class);
                constructor2.newInstance("heweii");//创建对应构造器的对象
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    打印结果,确实是ok的

    Age:50
    Name:heweii
    

    2.获取普通方法

    在Programmer中创建以下方法

    public void method1(){
            System.out.println("method1:");
        }
    
        public void method2(String str){
            System.out.println("method2:"+str);
        }
    
        private void method3(int num){
            System.out.println("method3:"+num);
        }
    
        protected void method4(double dou){
            System.out.println("method4:"+dou);
        }
    

    要注意的是,在调用方法的时候需要该类的实例,这个也好理解,访问类的非静态方法必须通过该类的对象访问

    proClass.getDeclaredMethods();//所有方法
                proClass.getMethods();//公共方法
    
                //获取带参的方法
                Method method1 = proClass.getDeclaredMethod("method4",double.class);
                Object o = proClass.getConstructor().newInstance();//默认构造方法
                method1.setAccessible(true);//非公共方法必须要
                method1.invoke(o,18.88);
    

    完全ok

    method4:18.88
    

    3.获取成员变量

    在Programmer中新增以下字段

    public String name;
        private int age;
        protected double weight;
    
    proClass.getDeclaredFields();//所有字段
                proClass.getFields();//公共字段
    
                //获取公共的成员变量
                Field field = proClass.getField("name");
                Object obj = proClass.getConstructor().newInstance();//默认构造方法
                field.set(obj , "hawaii");//赋值
                System.out.println("Field---Name:"+((Programmer)obj).name);
    
    Field---Name:hawaii
    

    再回头看上一篇的利用反射实现依赖注入的代码,是不是就看起来很简单了

    public static void bindView(final Activity activity){
            Class<Activity> activityClass = (Class<Activity>) activity.getClass();
            Field[] fields = activityClass.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(BindView.class)){
                    int id = field.getAnnotation(BindView.class).value();
                    View view = activity.findViewById(id);
                    field.setAccessible(true);
                    try {
                        field.set(activity , view);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
    
            Method[] methods = activityClass.getDeclaredMethods();
            for (final Method method : methods) {
                OnClick onClick = method.getAnnotation(OnClick.class);
                if (onClick != null) {
                    int[] ids = onClick.value();
                    for (int id : ids) {
                        activity.findViewById(id).setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                method.setAccessible(true);
                                try {
                                    method.invoke(activity);
                                } catch (IllegalAccessException e) {
                                    e.printStackTrace();
                                } catch (InvocationTargetException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    }
                }
            }
        }
    

    参考在线JavaApi链接
    http://tool.oschina.net/apidocs/apidoc?api=jdk_7u4

    相关文章

      网友评论

          本文标题:Android依赖注入之反射

          本文链接:https://www.haomeiwen.com/subject/zghujctx.html