Android-自定义注解-反射基础

作者: MonkeyLei | 来源:发表于2019-07-10 10:15 被阅读0次

    Let’s go

    上一章Android-自定义注解-注解基础-自定义注解我们基本上入门了这个注解的基本的东西,具体用途我们还需要学了反射之后就大概有个印象了。然后就可以尝试去使用反射做一些事情,想想butterknife….

    认识一下

    什么事反射?反射有什么用?我们一起来了解下相关资料…

    什么事反射(来自百度百科)

    image

    先了解这点就行。就是可以获取一个类的属性,方法等信息,感觉就是说你可以不用知道那个类到底有什么属性,什么方法,我们就获取所有的属性和方法,然后可以去invoke方法,获得各种定义的变量。

    举个例子(下面方法你可以获取到testTv2这个变量,可以获取到onCreate、clickView等方法信息):

    public class MainActivity extends AppCompatActivity {
        public TextView testTv2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        public void clickView(){
    
        }
    }
    

    知道就行。后面看看怎么操作这个东东。另外了解下一些知识点(来自百度百科)

    image

    阅读一下还是挺有意思的!

    反射有什么用?

    逆向代码 ,例如反编译
    与注解相结合的框架 例如Retrofit
    单纯的反射机制应用框架 例如EventBus 2.x
    动态生成类框架 例如Gson
    
    举个简单例子:加载游戏可能会涉及到高、低、中帧率模式,一般进入游戏你可以用switch, if等判断,
    你也可以用利用类名称产生一个加载实例对象,进而渲染不同的。比如你的渲染类有HighRender, LowRender,
     MiddleRender三个渲染类。你可以Class.forName("xxxRender").newInstance()产生一个渲染对象。
    紧紧几行代码就可以搞定!貌似酷酷滴...
    

    说点不好的,其实反射动态生成对象的时间有可能比你直接生成的时间慢很多(我之前利用反射findviewbyid发现比直接findviewbyid慢40倍,纳秒级! 还好是纳秒级,不然没法玩了….但是这样也暴露了单纯的反射某些情况获取不是高效的。所以我之前有提到说butterknife不是单纯的反射….理解如果有偏差,后面我们再来更正,学习总是会有不对的地方-实践出真知)

    来简单实践下

    我们就简单看看反射有哪些方法供我们使用,主要是java.lang.Class,以及java.lang.reflect和两个东东!!!

    java.lang.Class和java.lang.reflect

    我们想要获取一个类的属性,方法等,就需要Class这个类,这个类获取的属性(filed、method等),然后想要获取具体的method的名称等就需要java.lang.reflect这个包里面很多相关的类,进而通过类具体的方法获取具体的属性值。
    看下java.lang.Class相关api,你就大体了解了咯….

    image image

    看下java.lang.reflect,你就可以利用获取的file, method等对象去调用具体的方法获取值。

    image

    So,到这里我们基本知道了,原来可以这样的。那具体我们还是来段测试代码吧,我们就搞个java工程就行,不用非得搞android工程….或者Android工程里面随便新建一个测试类,搞个void main(String[] args)函数就可以运行了塞! (有些测试之前有了解,所以顺便调皮一下….看看,还有些无聊的测试,喵喵)

    package com.test.com.mylibrary;
    
    public class TestReflect2 {
        private int dontfuck = 0;
        public void setDontfuck(int _dontfuck){
            this.dontfuck = _dontfuck;
        }
    }
    
    package com.test.com.mylibrary;
    
    import android.util.Log;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class TestReflect {
        private int dontfuck = 0;
        public void setDontfuck(int _dontfuck){
            this.dontfuck = _dontfuck;
        }
        public static void main(String[] args){
            try {
                ///< 这个地方要全路径...com.test.com.mylibrary.TestReflect2
                TestReflect2 testReflect2 = (TestReflect2)Class.forName("com.test.com.mylibrary.TestReflect2").newInstance();
                ///< 只能获取public的
                Field[] fields =  testReflect2.getClass().getFields();
                long firstTime = System.nanoTime();
                for ( int i = 0; i < fields.length; ++i){
                    System.out.println("field'name = " + fields[i].getName());
                }
                System.out.println("循环time1=" + (System.nanoTime() - firstTime));
                firstTime = System.nanoTime();
                ///< 这种遍历效率更好,后空再琢磨....
                for ( Field field : fields){
                    System.out.println("field'name = " + field.getName());
                }
                System.out.println("循环time2=" + (System.nanoTime() - firstTime));
    
                ///< 可以获取private的....
                fields =  testReflect2.getClass().getDeclaredFields();
                for ( int i = 0; i < fields.length; ++i){
                    System.out.println("delared field'name = " + fields[i].getName());
                }
                ///< 获取所有的,包括继承来的public版本的?? 这个地方可能涉及到class声明一个类之后有哪些变化的机制,有空可以研究下...
                Method[] methods = testReflect2.getClass().getMethods();
                for (Method method : methods){
                    System.out.println("method'name = " + method.getName());
                }
                ///< 获取自己声明的-这样方法要少一点
                methods = testReflect2.getClass().getDeclaredMethods();
                for (Method method : methods){
                    System.out.println("delared method'name = " + method.getName());
                }
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    

    看结果:

    image

    可以看一看哟,少年。还是有点意思的哈,有什么不明白的可以看看api文档….api

    反射还有很多东西

    基础我们到这里,后面继续深入一下下看看Android里面我们怎么搞~~~嗖嗖的…下雨了,记得照顾好记几个…

    相关文章

      网友评论

        本文标题:Android-自定义注解-反射基础

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