Android初级——Reflect简单使用

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:只是作为梳理,也希望能够帮到人,千万别喷我。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值