Android 注解和反射原理和实现学习(下)

来源:互联网 发布:淘宝内部优惠卷怎么做 编辑:程序博客网 时间:2024/03/29 01:05

如何调用类中的private方法

1.创建一个类的实例
在得到一个类的Class对象之后,我们可以利用类Constructor去实例化该对象。Constructor支持泛型,也就是它本身应该是Constructor<T>。这个类有一个public成员函数:T newInstance(Object... args),其中args为对应的参数,我们通过Constructor的这个方法来创建类的对象实例。实例Class类的方法有两种,一种是利用Constructor类调用newInstance()方法,另一种就是利用Class类本身的newInstance()方法创建一个实例,构造函数无参数两种方法实现的效果是一样的。如果构造函数有多个,那就不一样了,不同的构造函数创建的对象不一样。

// 加载指定的类Class<?> clazz = Class.forName(cName);          // 利用newInstance()方法,获取构造方法的实例// Class的newInstance方法只提供默认无参构造实例// Constructor的newInstance方法提供带参的构造实例Constructor<?> constructor = clazz.getConstructor();Object obj = constructor.newInstance();    //如果是无参数的构造函数创建实例,用这个方法简单一些//Object obj = clazz.newInstance();

2.行为(执行)
Method类中包含着类的成员方法的信息。在Method类中有一个public成员函数:Object invoke(Object receiver, Object... args),参数receiver指明了调用对象,参数args指明了该方法所需要接收的参数。由于我们是在运行时动态的调用类的方法,无法提前知道该类的参数类型和返回值类型,所以传入的参数的类型是Object,返回的类型也是Object。如果某一个方法是Java类的静态方法,那么Object receiver参数可以传入null,因为静态方法从不属于对象。

3.属性
对类的成员变量进行读写,在Field类中有两个public方法:Object get(Object object),该方法可用于获取某成员变量的值;Void set(Object object, Object value),该方法设置某成员变量的值。其中,Object参数是需要传入的对象;如果成员变量是静态属性,在object可传入null。
 //获取和设置属性值 Field field = clazz.getField("i"); field.setAccessible(true); Object obj = clazz.newInstance(); Object valuen = field.get(obj); field.set(obj,2);
整个的代码

 //获取Class对象 String className = "com.kayak.annotationdemo.E"; Class<?> clazz = Class.forName(className);  //获取到无参数的构造方法 Constructor<?> constructor = clazz.getConstructor(); //创建实例 Object object = constructor.newInstance(); Class<?>[] parameterTypes = new Class<?>[]{String.class,Context.class}; //获取指定的方法 Method method = clazz.getDeclaredMethod("mtest",parameterTypes); method.setAccessible(true); Object[] values = new Object[]{"md",this}; method.invoke(object,values);

LoadMethod.java的优化处理代码

import java.lang.reflect.Constructor;import java.lang.reflect.Method;public class LoadMethodEx {    /**     * 在运行时加载指定的类,并调用指定的方法     * @param cName       Java的类名     * @param MethodName  方法名     * @param params      方法的参数值     * @return     */    public Object Load(String cName, String MethodName, Object[] params) {        Object retObject = null;        try {            // 加载指定的类            Class<?> clazz = Class.forName(cName);                        // 利用newInstance()方法,获取构造方法的实例            // Class的newInstance方法只提供默认无参构造实例            // Constructor的newInstance方法提供带参的构造实例            Constructor<?> ct = clazz.getConstructor();            Object obj = ct.newInstance();            // 根据方法名获取指定方法的参数类型列表            Class<?> paramTypes[] = this.getParamTypes(clazz, MethodName);            // 获取指定方法            Method meth = clazz.getMethod(MethodName, paramTypes);            meth.setAccessible(true);            // 调用指定的方法并获取返回值为Object类型            retObject = meth.invoke(obj, params);         } catch (Exception e) {            System.err.println(e);        }                return retObject;    }        /***获取参数类型,返回值保存在Class[]中*/    private Class<?>[] getParamTypes(Class<?> cls, String mName) {    Class<?>[] clazz = null;               /**Note: 由于我们一般通过反射机制调用的方法,是非public方法         * 所以在此处使用了getDeclaredMethods()方法*/        Method[] mtd = cls.getDeclaredMethods();            for (int i = 0; i < mtd.length; i++) {            if (!mtd[i].getName().equals(mName)) {            // 不是我们需要的参数,则进入下一次循环                continue;            }               clazz = mtd[i].getParameterTypes();        }        return clazz;    }}

参考文章:利用java反射技术阻止通过按钮关闭对话框连接:点击打开链接

下面添上一段利用java反射技术阻止通过按钮关闭对话框的代码

package crazypebble.androidreflection;import java.lang.reflect.Field;import android.app.Activity;import android.app.AlertDialog;import android.content.DialogInterface;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class MainActivity extends Activity {    /** Called when the activity is first created. */    private static Button btnHandler = null;    private static Button btnShowing = null;    AlertDialog alertDialog = null;        @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);            btnHandler = (Button)findViewById(R.id.btn_mHandler);        btnHandler.setOnClickListener(new ButtonListener());                btnShowing = (Button)findViewById(R.id.btn_mShowing);        btnShowing.setOnClickListener(new ButtonListener());                alertDialog = new AlertDialog.Builder(this)                .setTitle("abc")                .setMessage("Content")                .setIcon(R.drawable.icon)                .setPositiveButton("确定", new PositiveClickListener())                .setNegativeButton("取消", new NegativeClickListener())                .create();    }        private class ButtonListener implements OnClickListener {        @Override        public void onClick(View v) {            switch (v.getId()) {            case R.id.btn_mHandler:                modify_mHandler();                alertDialog.show();                break;            case R.id.btn_mShowing:                alertDialog.show();                break;            default:                break;            }        }    }        private class PositiveClickListener implements android.content.DialogInterface.OnClickListener {        @Override        public void onClick(DialogInterface dialog, int which) {            // 方法二时启用            modify_dismissDialog(false);        }    }        private class NegativeClickListener implements android.content.DialogInterface.OnClickListener {        @Override        public void onClick(DialogInterface dialog, int which) {            // 方法一时启用            //dialog.dismiss();            // 方法二时启用            modify_dismissDialog(true);        }    }        /*     * 第一种方法:修改AlertController类的private成员变量mHandler的值     */    public void modify_mHandler() {        try {            Field field = alertDialog.getClass().getDeclaredField("mAlert");            field.setAccessible(true);            // 获取mAlert变量的值            Object obj = field.get(alertDialog);            field = obj.getClass().getDeclaredField("mHandler");            field.setAccessible(true);            // 修改mHandler变量的值,使用新的ButtonHandler类            field.set(obj, new MyButtonHandler(alertDialog));                    } catch (Exception e) {            e.printStackTrace();        }    }        /*     * 第二种方法:修改dismissDialog()方法     */    public void modify_dismissDialog(boolean flag) {        try {            Field field = alertDialog.getClass().getSuperclass().getDeclaredField("mShowing");            field.setAccessible(true);            // 将mShowing变量设为false,表示对话框已经关闭            field.set(alertDialog, flag);            alertDialog.dismiss();        } catch (Exception e) {            e.printStackTrace();        }    }}

package crazypebble.androidreflection;import java.lang.ref.WeakReference;import android.content.DialogInterface;import android.os.Handler;import android.os.Message;public class MyButtonHandler extends Handler{    // Button clicks have Message.what as the BUTTON{1,2,3} constant    private static final int MSG_DISMISS_DIALOG = 1;        private WeakReference<DialogInterface> mDialog;    public MyButtonHandler(DialogInterface dialog) {        mDialog = new WeakReference<DialogInterface>(dialog);    }    @Override    public void handleMessage(Message msg) {        switch (msg.what) {                        case DialogInterface.BUTTON_POSITIVE:            case DialogInterface.BUTTON_NEGATIVE:            case DialogInterface.BUTTON_NEUTRAL:                ((DialogInterface.OnClickListener) msg.obj).onClick(mDialog.get(), msg.what);                break;        }    }}

反射机制通过void setAccessible(boolean flag)方法可以得到一个类的private的方法和属性,使用这些private的方法和属性,已经可以做一些超越限制的事情了,从而也面临了一些安全性的问题。

0 0
原创粉丝点击