如何调用类中的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的方法和属性,已经可以做一些超越限制的事情了,从而也面临了一些安全性的问题。