Android初级——Reflect简单使用

来源:互联网 发布:linux tmp 手动清理 编辑:程序博客网 时间:2024/06/14 18:51

Reflect的简单使用。
如果一个类当中的变量和方法为私有时,我们在其它地方就无法通过新建这个类的实例来获取它,这时候就可以采用Reflect(反射)机制来解决这个问题。通过反射我们能够获取某个类中的私有成员。

背景:
Android新人,听任神说自己学会的东西要写出来,有利于自己梳理和使用。
在学习师兄代码的时候,遇到了Reflect这个东西,一开始看到的时候,Class、Field、method完全看不懂,只能百度,然后看到了这位前辈(hfreeman2008)的博客里讲了这个知识点,于是学习了,不过前辈的代码有点长,我在学习的时候精简了这个例子,并有一些地方采用了不同的做法,看起来更为简单,希望能够帮助到同样第一次接触到Reflect的朋友们(因为转载需要向前辈申请,所以我这里就没有转载和贴链接了,不太懂这些。。。)。

方法:
1.创建一个目标对象的实例(myClass),然后赋给一个新的Class对象(clazz)。
2.通过Field/Method来获取到目标类中的变量(aInt)或方法(setInt(int aInt))。
3.将Field/Method.setAccessible属性设置为true。
4.通过field.get(myClass)来获取变量,通过method.invoke(myclass)来执行方法。
代码如下:

MyClass.java

package com.example.qicaizi.reflecttest2;import android.util.Log;/** * Created by qicaiZI on 2017/7/29. */public class MyClass {    private static final String TAG = "MyClass";    private int aInt = 0;    private boolean bBoolean = false;    private String sString = "test";    public MyClass() {        Log.d(TAG, "public MyClass Constructor");    }    public MyClass(int aInt, boolean bBoolean, String sString) {        Log.d(TAG, "private MyClass Constructor");        this.aInt = aInt;        this.bBoolean = bBoolean;        this.sString = sString;    }    private void setInt(int aInt) {        int pre = this.aInt;        this.aInt = aInt;        Log.d(TAG, "private setInt,aInt: " + pre + " to " + this.aInt);    }    private void getAll() {        Log.d(TAG, "private getAll()");        Log.d(TAG, "aInt: " + aInt + "  bBoolean: " + bBoolean + "  sString: " + sString);    }}

MainActivity.java

package com.example.qicaizi.reflecttest2;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;import java.lang.reflect.Field;import java.lang.reflect.Method;public class MainActivity extends AppCompatActivity {    private static final String TAG = "MainActivity";    private MyClass myClass;    //Reflect相关对象    private Class clazz;    private Method method,method2;    private Field aInt, bBoolean, sString;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //创建一个目标类的实例(myClass),然后赋给一个新的Class对象(clazz)。        myClass = new MyClass();        clazz = myClass.getClass();        try {            //通过Method来获取目标类中我们想要的私有方法            //访问getAll方法,这里只能使用getDeclaredMethod。getMethod会报错            method2 = clazz.getDeclaredMethod("getAll");            method2.setAccessible(true);            method2.invoke(myClass);            //通过Field来获取目标类中我们想要的私有变量,这里也只能使用getDeclaredField            aInt = clazz.getDeclaredField("aInt");            aInt.setAccessible(true);            //这里打印结果不是预期中的MyClass中的初始化值0,而是指向"aInt"变量的一个路径            Log.d(TAG, "aInt: " + aInt);            //所以我们用aInt.get(myClass)来获取它的值,这里获取到的是object型,不是int。打印结果为0            Log.d(TAG, "aInt: " + aInt.get(myClass));            //这里我们就可以用Field自带的方法来操作了,用Field.set方法可以改变获取到的变量的值。打印结果为1            aInt.setInt(myClass, 1);            Log.d(TAG, "aInt: " + aInt.get(myClass));            //如果目标类中私有方法包括参数,如MyClass中的setInt(int aInt),            //那么这里传入相应的("方法名", ***.class)就可以了            method = clazz.getDeclaredMethod("setInt", int.class);            method.setAccessible(true);            //用method.invoke来执行MyClass中的setInt方法。再打印一次,结果为2            method.invoke(myClass, 2);            Log.d(TAG, "aInt" + aInt.get(myClass));            //最后再调用一次getAll,前面用method2获取,此处不必重新获取            method2.invoke(myClass);        } catch (Exception e) {            e.printStackTrace();        }    }}

打印结果
这里写图片描述

PS:只是作为梳理,也希望能够帮到人,千万别喷我。。。

原创粉丝点击