Android 让反射变的简单
Posted 安卓开发-顺
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 让反射变的简单相关的知识,希望对你有一定的参考价值。
目录
一、通过反射执行方法
进入主题,先列出核心步骤。
第一步:获取Class对象
第二步:通过Class对象获取要执行的方法
第三步:执行方法
下面用一个简单的例子来演示下,一个MainActivity,一个ReflexUtil类,先贴上代码
package com.zs.test;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.zs.test.reflex.ReflexUtil;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ReflexUtil.testReflexMethod(this);
//示例一、通过反射调用方法
try
//第一步 获取class对象
//方式一 通过对象实例的getClass方法来获取
ReflexUtil reflexUtil = new ReflexUtil();
Class<? extends ReflexUtil> aClass = reflexUtil.getClass();
//方式二 通过类名.class获取
// Class<ReflexUtil> aClass = ReflexUtil.class;
// Class<?> aClass = Class.forName("com.zs.test.reflex.ReflexUtil");
//第二步 获取方法
Method method = aClass.getDeclaredMethod("Log", String.class);
//针对private方法进行权限设置
method.setAccessible(true);
//第三步 执行此方法
//静态方法直接调用即可 传入当前方法所属对象
// method.invoke(null, "tttttttttttt");
//非静态方法必须构造一个对象出来 这里演示通过构造方法来构造,其实可以直接使用reflexUtil 不用构造
//直接使用上面创建的reflexUtil实例
// method.invoke(reflexUtil,"not static");
Constructor<?> constructor = aClass.getConstructor();
Object target = constructor.newInstance();
method.invoke(target,"not static");
catch (Exception e)
Log.i("ZS","=== reflex error == " + e.toString());
e.printStackTrace();
//示例二、通过反射修改对象属性值
//第一步 获取class对象
Class<ReflexUtil> reflexUtilClass = ReflexUtil.class;
//第二步 获取指定属性
try
Field age = reflexUtilClass.getDeclaredField("age");
//第三步 修改属性值
//设置权限
age.setAccessible(true);
//构造对象
ReflexUtil reflexUtil = reflexUtilClass.newInstance();
age.set(reflexUtil,30);
int age2 = reflexUtil.getAge();
Log.i("ZS","=== reflex age2 == " + age2);
catch (NoSuchFieldException | IllegalAccessException | InstantiationException e)
e.printStackTrace();
private void toast(String content, boolean isShow)
if (isShow)
Toast.makeText(this, content, Toast.LENGTH_LONG).show();
package com.zs.test.reflex;
import android.content.Intent;
import android.util.Log;
import com.zs.test.MainActivity;
import com.zs.test.SecondActivity;
import java.lang.reflect.Method;
/**
* java 反射学习
*/
public class ReflexUtil
private int age = 25;
public int getAge()
return age;
/**
* 反射调用MainActivity的startActivity方法
* @param activity
*/
public static void testReflexMethod(MainActivity activity)
//第一步: 获取 class对象
//方式1、通过类名.直接获取
Class<MainActivity> class1 = MainActivity.class;
//方式2、通过调用对象的getClass来获取
Class<? extends MainActivity> class2 = activity.getClass();
//方式3、通过Class.forName(全路径)来获取
try
Class<?> class3 = Class.forName("com.zs.test.MainActivity");
catch (ClassNotFoundException e)
e.printStackTrace();
//第二步:获取对应方法
try
//获取类本身或者父类定义的public方法 参数一是方法名 参数二是参数
Method startActivity = class1.getMethod("startActivity", Intent.class);
Intent intent = new Intent(activity, SecondActivity.class);
//第三步 执行方法
startActivity.invoke(activity, intent);
//获取类本身定义的方法(public/protected/private)
Method toast = class2.getDeclaredMethod("toast", String.class, boolean.class);
//针对私有方法进行权限授予
toast.setAccessible(true);
//第三步 执行方法
toast.invoke(activity, "hhh", true);
catch (Exception e)
e.printStackTrace();
/**
* 我们假设此方法是系统隐藏方法,普通方式调用不到
* @param s
*/
private void Log(String s)
Log.i("ZS"," =============== " + s);
代码如上图所示,下面以执行ReflectUtil中的Log方法为例来分析
1、先分析第一步获取Class对象
- 方式1、通过调用对象实例的getClass来获取
ReflexUtil reflexUtil = new ReflexUtil();
Class<? extends ReflexUtil> aClass = reflexUtil.getClass();
- 方式2、通过类名.class来获取
Class<ReflexUtil> aClass = ReflexUtil.class;
- 方式3、通过Class.forName(全路径)来获取
try
Class<?> class3 = Class.forName("com.zs.test.MainActivity");
catch (ClassNotFoundException e)
e.printStackTrace();
这三种方式有何区别?我个人推荐的使用顺序是方式一 > 方式二 >方式三
方式一 可以直接得到对象的实例,后续执行方法时也无需再通过构造函数构造对象(静态方法除外,因为静态方法不需要构建对象实例,下面还会讲到),是我个人最优推荐
方式二 很简单也很好理解,只是不能拿到对象实例,后续还要构造对象实例,是我个人次优推荐
方式三 很强大如果前两种方式都不能用就用此方式来获取,其缺点是手写路径容易出错,类全路径可能会变,类也可能会消失(比如这个类被删除了),还要构造对象实例,是我个人最后推荐
2、在分析第二步,通过Class对象获取要执行的方法
Method method = aClass.getDeclaredMethod("Log", String.class);
目标方法是这样的,贴出来 private void Log(String s) Log.i("ZS"," =============== " + s);
解释下这里的 getDeclaredMethod
参数1:方法名
参数2...n 该方法需要的参数的类型,比如还有第三个参数是个boolean值,就变成
Method method = aClass.getDeclaredMethod("Log", String.class,boolean.class);
获取方法还有其他方式,区别如下:
Method getMethod(String name, Class[] params) -- 获取类本身或者父类定义的public方法
Method[] getMethods() -- 获取类本身或者父类定义的所有public方法
Method getDeclaredMethod(String name, Class[] params) --获取类本身定义的方法(public/protected/private)
Method[] getDeclaredMethods() -- 获取类本身定义的所有方法(public/protected/private)
3、最后分析第三步,执行方法
(1)针对private方法要进行权限设置
method.setAccessible(true);
(2)静态方法直接调用即可,对象实例传null就可以,瞎传也行,根本不校验,但是方法如果有返 回值的情况下,还是要传入一个对象实例
method.invoke(null, "tttttttttttt");
(3)非静态方法必须构造一个对象出来
//方式一、通过对象的newInstance()方法来构造 调用的是默认的空构造方法
ReflexUtil reflexUtil = aClass.newInstance();
//方式二、通过对象的构造方法来构造,这种方式可以指定构造方法
Constructor<?> constructor = aClass.getConstructor();
Object target = constructor.newInstance();
//假如有个string参数的构造方法可以这么写来得到
Constructor<?> constructor = aClass.getConstructor(String.class);
Object target = constructor.newInstance("aaa");
(4)执行目标方法
method.invoke(target,"not static");
二、通过反射修改对象属性值(非final修饰)
进入主题,先列出核心步骤。
第一步:获取Class对象
第二步:通过Class对象获取目标属性
第三步:修改属性值
1、获取Class对象同上,不在具体分析
Class<ReflexUtil> reflexUtilClass = ReflexUtil.class;
2、通过Class对象获取目标属性
Field age = reflexUtilClass.getDeclaredField("age");
获取方法还有其他方式,区别如下:
Field getField(String name) -- 获取类本身或者父类定义的public字段
Field[] getFields() -- 获取类本身或者父类定义的所有public字段
Field getDeclaredField(String name) -- 获取类本身定义的字段(public、protected、private)
Field[] getDeclaredFields() -- 获取类本身定义的所有字段(public、protected、private)
3、修改属性值
(1)针对private方法要进行权限设置
age .setAccessible(true);
(2)静态属性直接修改即可,对象实例传null就可以,瞎传也行,根本不校验
age.set(null,30);
(3)非静态方法必须构造一个对象出来
ReflexUtil reflexUtil = reflexUtilClass.newInstance();
(4)修改属性值
age.set(reflexUtil,30);
以上是关于Android 让反射变的简单的主要内容,如果未能解决你的问题,请参考以下文章