Moosphan / Android-Daily-Interview

:pushpin:每工作日更新一道 Android 面试题,小聚成河,大聚成江,共勉之~

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

2019-05-29:什么是反射机制?反射机制的应用场景有哪些?

Moosphan opened this issue · comments

2019-05-29:什么是反射机制?反射机制的应用场景有哪些?

Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。
应用场景:

  1. 逆向代码,例如反编译
  2. 与注解相结合的框架,如 Retrofit
  3. 单纯的反射机制应用框架,例如 EventBus(事件总线)
  4. 动态生成类框架 例如Gson
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;


/**
 * 对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,
 * 我们都能够对它的方法和属性进行调用。
 * 我们把这种动态获取对象信息和调用对象方法的功能称之为 反射机制
 */
/**
 * 所谓反射其实是获取类的字节码文件,
 * 也就是.class文件,那么我们就可以通过Class这个对象进行获取
 */
public class HookTest {

    public static void main(String[] args) {
        //第一种方式
        LoopTest loopTest = new LoopTest();
        Class aClass = loopTest.getClass();
        System.out.println(aClass.getName());
        //第二种方式
        Class aclass2 = LoopTest.class;
        System.out.println(aclass2.getName());
        //第三种方式
        try {
            Class aclass3 = Class.forName("LoopTest");
            System.out.println(aclass3.getName());
        }catch (ClassNotFoundException ex){
            ex.printStackTrace();
        }

        /**
         * 那么这3中方式我们一般选用哪种方式呢?第一种已经创建了对象,那么这个时候就不需要去进行反射了,
         * 显得有点多此一举。第二种需要导入类的包,依赖性太强。所以我们一般选中第三种方式。
         */

        /**
         * 三、通过反射获取类的构造方法、方法以及属性
         */

        /**
         * 1、获取构造方法
         */
        Constructor[]constructors = aclass2.getConstructors();
        System.out.println("获取构造方法:");
        for (Constructor constructor1 : constructors){
            System.out.println(constructor1.getName());
        }
        System.out.println("获取类的属性:");
        Field[] fields = aclass2.getFields();
        //88888
        System.out.println("获取类的方法:");
        Method[]methods = aclass2.getMethods();
        for (Method method : methods){
            System.out.println(method.getName());
        }

        /**
         * 反射执行方法
         */

        try {   Class aclass4 = Class.forName("LoopTest");
            Method method   = aclass4.getDeclaredMethod("method",String.class);
            Constructor ct = aclass4.getConstructor(null);
            Object obj = ct.newInstance(null);
            method.invoke(obj,"反射调用");
        } catch (Exception e) {
            e.printStackTrace();
        }


        /**
         * Android中使用场景:其实很多用过的EventBus 、Retrofit 都有涉猎 可以去看看源码
         */
    }

}

java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
静态编译:在编译时确定类型,绑定对象。
动态编译:在运行时确定类型,绑定对象。
反射机制的优缺点:
优点:运行期类型的判断,动态加载类,提高代码灵活度。
缺点:性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java代码要慢很多。

概念及介绍

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法
1.先得到class对象(类名、类本身、类的对象)
2.通过class对象的对应方法得到构造器、属性、方法
具体使用

应用场景
我这边用过的就是组件化开发的时候用来进行页面的跳转 其他很多框架内部应该都有所用到 不是很清楚

反射主要体现在动态这个词,使用灵活、性价比高。
举例:
1、ButterKnife注解生成的类,使用反射进行inject,一个类统筹全局。(体现性价比)
2、Retrofit 定义一个interface就可以进行网络请求。(体现灵活)
3、解耦
4、逆向Hook,Xposed插件通过反射调用任意方法,为所欲为。
Retrofit之所以简单易用,Java的动态代理功不可没而动态代理中反射又是重中之重,interface相当于配置文件,之后动态代理进行方法的加强,完成请求。

单纯的反射机制应用框架,例如 EventBus(事件总线)这个好像错了吧 eventbus并不是单纯的反射,只是少数用到了反射 其实还是使用apt

单纯的反射机制应用框架,例如 EventBus(事件总线)这个好像错了吧 eventbus并不是单纯的反射,只是少数用到了反射 其实还是使用apt

ButterKnife 吧?EventBus用到APT 了?

你去看看就知道了

还真是哈哈

可以的

往往标记语言解析成类都会用到反射。比如

  1. android中xml解析成具体的类 是用了反射
  2. fastjson,gson等
    反射的另一个重要应用领域是动态代理,可以强解耦
    另外总结了一张表
    image

对于一个类,能够访问其任意的属性和方法,包括私有属性。
gson 动态解析生成对象的过程