java反射机制以及在android开发中的应用

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

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据