Android反射2-对反射语法的封装

news/2024/5/19 3:02:05 标签: android, 反射, 工具类

2 对基本反射语法的封装

前面介绍的种种语法,无论是反射出一个类,还是反射出一个构造函数井调用它,都是为了进一步读写类的方法和宇段,所以我们只要封装以下几个方法即可:

  • 反射出 一个构造 函数并调用它 。
  • 调用静态方法。
  • 调用实例方法 。
  • 获取和设置一个字段的值。
  • 对泛型的处理 。

2.1 反射出一个构造函数

   public static Object createObject(String className, Class[] pareTyples, Object[] pareVaules) {
        try {
            Class r = Class.forName(className);
            Constructor ctor = r.getDeclaredConstructor(pareTyples);
            ctor.setAccessible(true);
            return ctor.newInstance(pareVaules);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
final String className = "xxx.xxx.TestClassCtor";

Class r = Class.forName(className);

 //含参
Class[] p3 = {int.class, String.class};
Object[] v3 = {1, "bjq"};
Object obj = RefInvoke.createObject(className, p3, v3);

//无参
Object obj2 = RefInvoke.createObject(className, null, null);

2.2 调用实例方法

    public static Object invokeInstanceMethod(Object obj, String methodName, Class[] pareTyples, Object[] pareVaules) {
        if(obj == null)
            return null;

        try {
            //调用一个private方法
            Method method = obj.getClass().getDeclaredMethod(methodName, pareTyples); //在指定类中获取指定的方法
            method.setAccessible(true);
            return method.invoke(obj, pareVaules);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
    //3.1.获取类的private实例方法,调用它
    public void test3() {
        try {
            //创建一个对象
            Class[] p3 = {int.class, String.class};
            Object[] v3 = {1, "bjq"};
            Object obj = RefInvoke.createObject(className, p3, v3);

            //调用一个private方法
            Class[] p4 = {String.class};
            Object[] v4 = {"jianqiang"};
            Object result = RefInvoke.invokeInstanceMethod(obj, "doSomething", p4, v4);

            Object a = result;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

2.3 调用静态方法

    public static Object invokeStaticMethod(String className, String method_name, Class[] pareTyples, Object[] pareVaules) {
        try {
            Class obj_class = Class.forName(className);
            Method method = obj_class.getDeclaredMethod(method_name, pareTyples);
            method.setAccessible(true);
            return method.invoke(null, pareVaules);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
    //3.2.获取类的private静态方法,调用它
    public void test3_1() {
        try {
            Class[] p3 = {};
            Object[] v3 = {};
            RefInvoke.invokeStaticMethod(className, "work", p3, v3);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

2.4 获取并设置一个字段的值

 public static Object getFieldObject(String className, Object obj, String filedName) {
        try {
            Class obj_class = Class.forName(className);
            Field field = obj_class.getDeclaredField(filedName);
            field.setAccessible(true);
            return field.get(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public static void setFieldObject(String classname, Object obj, String filedName, Object filedVaule) {
        try {
            Class obj_class = Class.forName(classname);
            Field field = obj_class.getDeclaredField(filedName);
            field.setAccessible(true);
            field.set(obj, filedVaule);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 //4.1.获取类的private实例字段,修改它
    public void test4() {
        try {
            //创建一个对象
            Class[] p3 = {int.class, String.class};
            Object[] v3 = {1, "fhx"};
            Object obj = RefInvoke.createObject(className, p3, v3);

            //获取name字段,private
            Object fieldObject = RefInvoke.getFieldObject(className, obj, "name");

            //只对obj有效
            RefInvoke.setFieldObject(className, obj, "name", "hongxue123");

            Object fieldObject2 = RefInvoke.getFieldObject(className, obj, "name");

            int a = 1;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //获取类的private静态字段,修改它
    public void test4_1() {
        try {
            Object fieldObject = RefInvoke.getFieldObject(className, null, "address");
            RefInvoke.setFieldObject(className, null, "address", "ABCD");

            //静态变量,一次修改,终生受用
            TestClassCtor.printAddress();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

2.5 对泛型类的处理

public class AMN {

    private static final Singleton<ClassB2Interface> gDefault = new Singleton<ClassB2Interface>() {
        protected ClassB2Interface create() {
            ClassB2 b2 = new ClassB2();
            b2.id = 2;
            return b2;
        }
    };

    static public ClassB2Interface getDefault() {
        return gDefault.get();
    }
}
class ClassB2 implements ClassB2Interface{
    public int id;

    public void doSomething() {
        Log.v("hongxue", "ClassB2 doSomething");
    }
}
public interface ClassB2Interface {
    void doSomething();
}

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;
        }
    }
}
 public void test5() {
        try {
            //获取AMN的gDefault单例gDefault,gDefault是静态的
            Object gDefault = RefInvoke.getFieldObject("xxx.xxx.xxx.AMN", null, "gDefault");

            // gDefault是一个 android.util.Singleton对象; 我们取出这个单例里面的mInstance字段
            Object rawB2Object = RefInvoke.getFieldObject(
                    "xxx.xxx.xxx.Singleton",
                    gDefault, "mInstance");


            // 创建一个这个对象的代理对象ClassB2Mock, 然后替换这个字段, 让我们的代理对象帮忙干活
            Class<?> classB2Interface = Class.forName("xxx.xxx.xxx.ClassB2Interface");
            Object proxy = Proxy.newProxyInstance(
                    Thread.currentThread().getContextClassLoader(),
                    new Class<?>[] { classB2Interface },
                    new ClassB2Mock(rawB2Object));

            //把Singleton的mInstance替换为proxy
            RefInvoke.setFieldObject("xxx.xxx.xxx.Singleton", gDefault, "mInstance", proxy);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

2.6 RefInvoke.java

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class RefInvoke {

    public static Object createObject(String className, Class[] pareTyples, Object[] pareVaules) {
        try {
            Class r = Class.forName(className);
            Constructor ctor = r.getDeclaredConstructor(pareTyples);
            ctor.setAccessible(true);
            return ctor.newInstance(pareVaules);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public static Object invokeInstanceMethod(Object obj, String methodName, Class[] pareTyples, Object[] pareVaules) {
        if(obj == null)
            return null;

        try {
            //调用一个private方法
            Method method = obj.getClass().getDeclaredMethod(methodName, pareTyples); //在指定类中获取指定的方法
            method.setAccessible(true);
            return method.invoke(obj, pareVaules);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public static Object invokeStaticMethod(String className, String method_name, Class[] pareTyples, Object[] pareVaules) {
        try {
            Class obj_class = Class.forName(className);
            Method method = obj_class.getDeclaredMethod(method_name, pareTyples);
            method.setAccessible(true);
            return method.invoke(null, pareVaules);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public static Object getFieldObject(String className, Object obj, String filedName) {
        try {
            Class obj_class = Class.forName(className);
            Field field = obj_class.getDeclaredField(filedName);
            field.setAccessible(true);
            return field.get(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public static void setFieldObject(String classname, Object obj, String filedName, Object filedVaule) {
        try {
            Class obj_class = Class.forName(classname);
            Field field = obj_class.getDeclaredField(filedName);
            field.setAccessible(true);
            field.set(obj, filedVaule);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

http://www.niftyadmin.cn/n/1837345.html

相关文章

Don't Laugh!I'm An English Book笔记(一)

人体&#xff1a;所有的life都是由cell构成的&#xff0c;我看不到这些cell,大概是因为我的视力不太好吧。如果有一台microscope就可以看到chromosome了。连gene也可以看到了。&#xff1a;&#xff09;Cell聚集到一起形成tissue&#xff0c;再把tissue组织到一起形成organ。Or…

Flutter实现自己的表格组件

表格组件最终效果如下&#xff1a; 整个表格的数据为一个List<List<TableDetail>> tableList 每一行的数据为一个List<TableDetail> list 表格的数据实体类: class TableDetail {String title, content;TableDetail(String title, String content) {this…

java 支付宝回调校验签名_支付宝异步回调验证签名

今天做支付宝接口回调这块&#xff0c;不得不说&#xff0c;弄的我焦头烂额&#xff0c;翻了很多陈年旧帖&#xff0c;试了无数种解决坑的方案&#xff0c;在我成功解决的一瞬间&#xff0c;觉得非常有必要记录一下这些坑。签名验证错误的检查顺序(这里是基于使用官方给的demo&…

一个有趣的C#面试题

一次面试 做了一道题内容如下这道题是这样的 有四个类publicclassClassA { public virtual void print() { Console.WriteLine("My ClassA"); } }publicclassClassB:ClassA { public override void print() { …

java面试面试官介绍了公司情况_面试官 | 什么是 Lambda?该如何使用?

作者 | Mingqi来源 | zhihu.com/question/20125256/answer/3241213081.什么是Lambda?我们知道&#xff0c;对于一个Java变量&#xff0c;我们可以赋给其一个“值”。如果你想把“一块代码”赋给一个Java变量&#xff0c;应该怎么做呢&#xff1f;比如&#xff0c;我想把右边那…

利用CSS控制打印(转载)

转载网址&#xff1a;http://blog.csdn.net/net_lover/archive/2004/07/06/35228.aspx 放在这里&#xff0c;算是一个备份 <style> media print{ INPUT {display:none} } </style> <TABLE border"0" style"font-size:9pt;" width"300p…

php 数组 按值 删除,3分钟短文 | PHP 根据值移除数组元素,哪个方法最简单?

原标题&#xff1a;3分钟短文 | PHP 根据值移除数组元素&#xff0c;哪个方法最简单&#xff1f;引言PHP 数组操作&#xff0c;之前我们讲了如何根据值&#xff0c;进行多维数组的排序。今天说一说&#xff0c;如何根据值&#xff0c;进行数组元素的删除。学习时间假设有一个一…

DevExpress ExpressScheduler 快速编译批处理文件

手动安装DevExpress的控件包源代码实在是让人受不了&#xff0c;写了一个批处理快速的生成bpl, dcp,以及dcu首先将ExpressScheduler 的源代码解压到一个目录。将下面的代码保存为Build.bat (不能改成其它文件名)&#xff0c;然后执行&#xff0c;等待&#xff0c;在Lib中就是所…