java中的反射机制:只要给定类的名字就可以得到所有类的信息。因为这个类的名字是可以在代码运行时动态指定的,所以利用java的反射机制比通过new的方式要灵活的多
在java中,通过new的方式创建的对象称为静态加载(编译时加载类),通过反射机制创建对象称为动态加载(运行时加载类)
java反射机制的使用方式
这里有个Human类如下
package com.myway5;
public class Human {
private String name;
private int age;
public String word;
public Human() {
// TODO Auto-generated constructor stub
}
public Human(String name) {
this.name = name;
}
public Human(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void speak(String word) {
System.out.println(word);
}
}
我们使用反射机制获取Human类所有的信息
package com.myway5;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Client {
public static void main(String[] args) {
// 获取类名等信息
Class class1 = Human.class;
System.out.println(class1.getName());
System.out.println(class1.getSimpleName());
System.out.println("***********构造方法**********");
Constructor[] cs = class1.getDeclaredConstructors();
for (Constructor constructor : cs) {
System.out.print(constructor.getName() + "(");
Class[] paramsType = constructor.getParameterTypes();
for (Class class2 : paramsType) {
System.out.print(class2.getName() + ",");
}
System.out.println(")");
}
System.out.println("**********公共成员变量************");
Field[] fields = class1.getFields();
for (Field field : fields) {
System.out.println(field.getType().getName() + ":" + field.getName());
}
System.out.println("**********公共方法**************");
Method[] methods = class1.getMethods();
for (Method method : methods) {
System.out.print(method.getName() + "(");
Class[] params = method.getParameterTypes();
for (Class class3 : params) {
System.out.print(class3.getName() + ",");
}
System.out.println(method.getReturnType().getName() + ")");
}
}
}
输出结果如下:
com.myway5.Human
Human
***********构造方法**********
com.myway5.Human(java.lang.String,int,)
com.myway5.Human(java.lang.String,)
com.myway5.Human()
**********公共成员变量************
java.lang.String:word
**********公共方法**************
getName(java.lang.String)
setName(java.lang.String,void)
getAge(int)
setAge(int,void)
wait(long,int,void)
wait(long,void)
wait(void)
equals(java.lang.Object,boolean)
toString(java.lang.String)
hashCode(int)
getClass(java.lang.Class)
notify(void)
notifyAll(void)
可以看到,所有公共的成员变量,方法都可以通过这个方式获取到,那么怎么调用其中的方法呢
public static void useMethod() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException,
InstantiationException, NoSuchMethodException, SecurityException {
Class class1 = Human.class;
Human man = (Human) class1.newInstance();//通过newInstance创建实例
Method method = class1.getMethod(“speak”, String.class);
Object object = method.invoke(man, new Object[] { “hello reflect” });
}
android开发中的使用后续更新
继上文更新:
android开发中常常会使用java的反射机制来更改一些系统底层无法更改的代码逻辑。比如说在AlertDialog的使用中,通过自带的setPositiveButton或者setNegativeButton时,一旦点击按钮都会退出dialog,有时候我们不希望他退出,比如用户登录时登录失败再次登录。那么一种解决办法 就是通过java的反射机制。
package com.myway5.java_reflect;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
public class MainActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setMessage("Hello Dialog")
.setTitle("对话框")
.setView(getLayoutInflater().inflate(R.layout.dialog_signin,null));
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog dialog=builder.create();
try {
Field field = dialog.getClass().getDeclaredField("mAlert");
field.setAccessible(true);
Object obj=field.get(dialog);
field=obj.getClass().getDeclaredField("mHandler");
field.setAccessible(true);
field.set(obj,new ButtonHandler(dialog));
}catch (Exception e){
e.printStackTrace();
}
dialog.show();
}
private static final class ButtonHandler 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 ButtonHandler(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;
case MSG_DISMISS_DIALOG:
//这里是点击后的逻辑,因为注释掉了dismiss(),dialog不会退出了
//((DialogInterface) msg.obj).dismiss();
}
}
}
}
其中
try {
Field field = dialog.getClass().getDeclaredField(“mAlert”);
field.setAccessible(true);
Object obj=field.get(dialog);
field=obj.getClass().getDeclaredField(“mHandler”);
field.setAccessible(true);
field.set(obj,new ButtonHandler(dialog));
}catch (Exception e){
e.printStackTrace();
}
这个部分就是通过反射获取AlertDialog的私有变量mAlert,然后获取mAlert的成员变量mHandler,将这个Handler设置成我们自己的ButtonHandler,这样就解决了点击后退出的问题
代码地址:https://github.com/joyme123/java_reflect
参考文章:http://www.oschina.net/question/163910_27112