• 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.敬请期待

  • 相关阅读:
    VS2008 编译出错 fatal error C1859: unexpected precompiled header error, simply rerunning the compiler might fix this problem
    解析XML出错,无法创建DOMDocument对象
    strncpy, strncpy_s
    Mongodb: Sort operation used more than the maximum 33554432 bytes of RAM
    node-cache
    【Boost】boost::string_algo详解2——find相关函数
    Compiler Error: Function call with parameters that may be unsafe
    fopen和fopen_s用法的比较
    fopen_s遇到的一个问题
    Data type conversion in MongoDB
  • 原文地址:https://www.cnblogs.com/tony-yang-flutter/p/12317728.html
Copyright © 2020-2023  润新知