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.敬请期待
浙公网安备 33010602011771号