反射封装类

本篇博客介绍java中最强大的技术:反射;反射包括以下技术:

  • 根据一个字符串得到一个类的对象
  • 获取一个类的所有公用或私有、静态或实例的字段、方法、属性
  • 对泛型的反射

根据一个字符串得到一个类

① getClass:通过一个对象获取它的类型,类型用class表示

String str = "hello";
Class num = str.getClass();
Log.e("----->>", ">>>" + num);

打印为:class java.lang.String

② Class.forName

这个方法用的最多,通过一个字符串获取类型,这个字符串由类的命名空间和类的名称组成,而通过getSuperclass方法,获取对象的父类型

    try {
            Class num02 = Class.forName("android.widget.Button");
            Class num03 = Class.forName("java.lang.String");
            Class num04 = num02.getSuperclass();
            Log.e(TAG, "02>" + num02);
            Log.e(TAG, "03>>" + num03);
            Log.e(TAG, "04>>" + num04);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

打印为:

android.widget.Button、java.lang.String、android.widget.TextView

③ 每个类都有class属性,可以得到这个类的类型

Class c01 = String.class;
        Class c02 = MainActivity.class;
        Class c03 = MainActivity.TAG.getClass();

        Log.e(TAG, "-02-->>" + c01 + ";;;>>>>" + c02 + "----->>" + c03);

打印为:class java.lang.String、class com.my.hookdemo.MainActivity、class java.lang.String

④基本类型:如Boolean等都有type属性,可以得到这个基本类型的类型:

        Class c01 = Boolean.TYPE;
        Class c02 = Byte.TYPE;
        Log.e(TAG, "-02-->>" + c01 + ";;;>>>>" + c02);

打印为:boolean、byte

下面贴上代码,封装了一些操作包括:反射构造函数、反射并调用private方法、反射并调用public方法、反射并调用public属性、设置一个字段,代码中有详细说明

package com.my.hookdemo.hook;

import android.util.Log;

public class TestClass {


    public String adds;
    private String names;

    public TestClass() {
    }

    private TestClass(String names) {
        names = names;
    }

    private TestClass(String a, String c) {
        adds = a;
        names = c;
    }


    public String getAdds() {
        return adds;
    }

    public void setAdds(String adds) {
        this.adds = adds;
    }

    public String getNames() {
        return names;
    }

    public void setNames(String names) {
        this.names = names;
    }

    private String doSomeThing() {
        return "hello world 的私有方法";
    }

    public void testMothod(String msg) {
        Log.e("---打印的值->>", "00>>>" + msg);
    }

    public static int testStatic(int values) {
        return values;
    }

    private void callPrivate(String key) {
        Log.e("---打印的值->>", "04>>>" + key);
    }

}


封装的Reflnvoke类

package com.my.hookdemo.hook;

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

public class Reflnvoke {

    /**
     *  反射出构造函数
     * @param className             类的名字
     * @param pareTypes             参数的类型
     * @param pareValues            参数的值
     * @return   object 对象的实例
     *
     * */
    public static Object createObject(String className, Class[] pareTypes, Object[] pareValues) {

        try {
            Class r = Class.forName(className);
            Constructor ctor = r.getDeclaredConstructor(pareTypes);
            ctor.setAccessible(true);
            return ctor.newInstance(pareValues);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 调用private方法
     *
     * @param obj               对应类的反射object
     * @param methodName        方法名字
     * @param pareTypes         参数类型
     * @param pareValue         参数值
     *
     * @return 返回方法的返回值,如果返回值为null,即返回为null,如果返回为string,则返回为string
     * */
    public static Object invokeInstanceMethod(Object obj, String methodName, Class[] pareTypes, Object[] pareValue) {

        if (obj == null) {
            return null;
        }
        try {
            Method method = obj.getClass().getDeclaredMethod(methodName, pareTypes);//在指定类中获取指定方法
            method.setAccessible(true);
            return method.invoke(obj, pareValue);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 调用静态方法
     * @param  className            类的名字
     * @param  methgod_name         方法名字
     * @param pareTypes             参数类型
     * @param pareValues            参数值
     *
     *  @return 返回方法的返回值,如果返回值为null,即返回为null,如果返回为string,则返回为string
     * */
    public static Object invokeStaticMethod(String className, String methgod_name, Class[] pareTypes, Object[] pareValues) {

        try {
            Class obj_class = Class.forName(className);
            Method method = obj_class.getDeclaredMethod(methgod_name, pareTypes);
            method.setAccessible(true);
            return method.invoke(null, pareValues);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取类的public 属性的值
     * @param className                 class的名字
     * @param object                    对应的object
     * @param fieldName                 对应的public 属性值
     *
     * */
    public static Object getFieldObject(String className, Object object, String fieldName) {

        try {
            Class obj_class = Class.forName(className);
            Field field = obj_class.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(object);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //设置一个字段
    public static void setFieldObject(String className, Object obj, String fieldName, Object fieldValue) {

        try {
            Class obj_class = Class.forName(className);
            Field field = obj_class.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(obj, fieldValue);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Object getStaticFieldObject(String className, String field) {
        return getFieldObject(className, null, field);
    }

    public static void setStaticFieldObject(String className, String fieldName, Object fieldValue) {

        setFieldObject(className, null, fieldName, fieldValue);
    }

//    public static Object getFieldObject(Object object, String fieldName) {
//        return getFieldObject(object.getClass(), object, fieldName);
//    }

}


调用处:

 try {
            Class r = Class.forName("com.my.hookdemo.hook.TestClass");
            Class[] p3 = {String.class, String.class};
            Object[] v3 = {"11", "stone"};
            Object object = Reflnvoke.createObject("com.my.hookdemo.hook.TestClass", p3, v3);

            TestClass testClass = (TestClass) object;
            testClass.testMothod("hello world");//调用public方法


            //调用soSomeThing私有方法,返回string类型,不传递参数
            String object02 = (String) Reflnvoke.invokeInstanceMethod(object, "doSomeThing", null, null);
            Log.e("---打印的值->>", "01>>>" + object02);

            Class[] p4 = {int.class};
            Object[] v4 = {7800};
            //调用testStatic静态方法,参数类型为p4,参数方法为v4
            int values = (int) Reflnvoke.invokeStaticMethod("com.my.hookdemo.hook.TestClass", "testStatic", p4, v4);
            Log.e("---打印的值->>", "02>>>" + values);

            //设置public属性adds为"你好"
            Reflnvoke.setFieldObject("com.my.hookdemo.hook.TestClass", object, "adds", "你好");
            String name = (String) Reflnvoke.getFieldObject("com.my.hookdemo.hook.TestClass", object, "adds");
            Log.e("---打印的值->>", "03>>>" + name);

            Class[] p5 = {String.class};
            Object[] v5 = {"调用了私有方法"};
            Reflnvoke.invokeInstanceMethod(object, "callPrivate", p5, v5);


            Reflnvoke.setFieldObject("com.my.hookdemo.hook.TestClass", object, "names", "设置private属性");
            String names = (String) Reflnvoke.getFieldObject("com.my.hookdemo.hook.TestClass", object, "names");
            Log.e("---打印的值->>", "05>>>" + names);

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

打印的结果为:

12-26 09:10:44.048 2308-2308/com.my.hookdemo E/---打印的值->>: 00>>>hello world
12-26 09:10:44.056 2308-2308/com.my.hookdemo E/---打印的值->>: 01>>>hello world 的私有方法
12-26 09:10:44.056 2308-2308/com.my.hookdemo E/---打印的值->>: 02>>>7800
12-26 09:10:44.056 2308-2308/com.my.hookdemo E/---打印的值->>: 03>>>你好
12-26 09:10:44.056 2308-2308/com.my.hookdemo E/---打印的值->>: 04>>>调用了私有方法
12-26 09:10:44.056 2308-2308/com.my.hookdemo E/---打印的值->>: 05>>>设置private属性

封装的工具类可以直接拿过来用

发布了15 篇原创文章 · 获赞 0 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qinggancha/article/details/103541800