Java对泛型进行反射实战

一、概述

  前两节接连介绍了,Java的反射技术,以及把Java的反射技术封装成类库。本节接下来介绍的内容都是基于以上两节来实现的。如果读者看起来吃力可以回过头看看前两节的内容,然后接着看本节内容。

二、实战

 整体流程描述:首先先定义一个泛型的单例类Singleton,然后在BookManger中实例化这个单例。IBook是一个接口。JavaBook和AndroidBook是IBook的具体实现类。ReflectUtil是反射工具类

 在BookManger中默认单例返回的是JavaBook。我们通过反射将其动态替换为默认返回AndroidBook。

 1.IBook.java

  

package com.yw.reflectjavalib.generic;

/**
 * book接口
 * create by yangwei
 * on 2020-02-07 16:59
 */
public interface IBook {
    void write();
    void read();
}

  

 2.JavaBook.java

package com.yw.reflectjavalib.generic;

/**
 * create by yangwei
 * on 2020-02-07 17:04
 */
public class JavaBook implements IBook {
    @Override
    public void write() {
        System.out.println("正在写java代码");
    }

    @Override
    public void read() {
        System.out.println("正在读java代码");
    }
}

  

 3.AndroidBook.java

package com.yw.reflectjavalib.generic;

import com.yw.reflectjavalib.LogUtil;


/**
 * create by yangwei
 * on 2020-02-07 17:07
 */
public class AndroidBook implements IBook  {
    @Override
    public void write() {
        LogUtil.e("正在写Android");
    }

    @Override
    public void read() {
        LogUtil.e("正在阅读Android");
    }


}

  

 4.BookManger

package com.yw.reflectjavalib.generic;

/**
 * book的管理类
 * create by yangwei
 * on 2020-02-07 17:03
 */
public class BookManager {
    private static final Singleton<IBook> getDefault = new Singleton<IBook>() {
        @Override
        protected IBook create() {
            return new JavaBook();
        }
    };

    public static IBook getDefault() {
        return getDefault.get();
    }

}

  

 5.Singleton

package com.yw.reflectjavalib.generic;

/**
 * 泛型单例
 * create by yangwei
 * on 2020-02-07 17:00
 */
public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
        }
        return mInstance;
    }
}

  

 6.ReflectGenericDemo

package com.yw.reflectjavalib.generic;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;

/**
 * 对泛型进行反射
 * <p>
 * 通过动态代理模式+反射把JavaBook替换成我们需要的AndroidBook。对BookManager进行代码注入
 * create by yangwei
 * on 2020-02-07 16:58
 */
public class ReflectGenericDemo {
    public static void main(String[] args) throws Exception {
        //获取Singleton的mInstance字段
        Class<?> singleton = Class.forName("com.yw.reflectjavalib.generic.Singleton");
        Field mInstanceField = singleton.getDeclaredField("mInstance");
        mInstanceField.setAccessible(true);
        //获取bookmanager的getDefault字段
        Class<?> bookManager = Class.forName("com.yw.reflectjavalib.generic.BookManager");
        Field getDefaultField = bookManager.getDeclaredField("getDefault");
        getDefaultField.setAccessible(true);
        //获取gedefault字段的值,其实就是Singleton实例
        Object getDefault = getDefaultField.get(null);
        
        //把JavaBook替换为AndroidBook
        mInstanceField.set(getDefault,new AndroidBook());
        BookManager.getDefault().read();

    }
}

  运行BookManger.getDefault().read()方法,我们发现打印出来的确实是“正在阅读Android”,如果把mInstanceFiled.set(getDefault,new AndroidBook)注释掉,则输出的是“正在阅读Java”。这种情况也可称之为Hook,利用这种技术我们可以做一些底层类的替换(android插件化相关)。例如:我们可以对AMS和PMS进行hook。或者对Instrumentation或者mCallback进行hook。

下一节将讲解动态代理,也是基于反射,比这一节的内容更为高级一点。一遍我们在做插件话hook的时候通常会用到proxy.newProxyInstance.敬请期待

posted on 2020-02-16 17:37  飘杨......  阅读(794)  评论(0编辑  收藏  举报