-
Android 反射获取私有方法,成员变量
2017-09-27 10:12:48public class AppInfo { private String mAppName; public String getAppName() { return mAppName; } public void setAppName(String appName) { this.mAppName = appName; } } ppublic class AppInfo { private String mAppName; public String getAppName() { return mAppName; } public void setAppName(String appName) { this.mAppName = appName; } }
获取方法
public static void test() { try { 获取class 实例 Class<?> clz = Class.forName("com.xxx.xxx.bean.AppInfo"); //获取object实例,即AppInfo实例,这里会调用无参构造方法 Object obj = clz.newInstance(); //调用方法setAppName,传入String 类型的参数 Method mothod1 = clz.getMethod("setAppName",String.class); //执行该方法,实参为"hhhhh",obj为要操作的对象 mothod1.invoke(obj,"hhhhh"); //调用getAppName 方法,不需要传参 Method mothod = clz.getMethod("getAppName"); //在obj对象中,执行该方法 String name = (String) mothod.invoke(obj); } catch (Exception e) { e.printStackTrace(); } }
获取成员变量
public void getField(Object obj) { Class<?> class1 = obj.getClass(); Field[] fields = class1.getDeclaredFields();//获取全部成员变量 Field[] fields = class1.getDeclaredFields(); for( Field field : fields ){ Log.i("test", "name==" + field.getName());//依次获取成员变量名 } Field field = class1.getDeclaredField("lottieDrawable");//获取变量名为lottieDrawable 的变量 field.setAccessible(true);//开放权限 LottieDrawable drawable = (LottieDrawable) field.get(obj);//从对象中获取该成员变量值 //field.getInt(obj),field.getBoolean(obj).... }
-
Android 通过反射获取系统组件的私有变量,并做更改
2017-07-06 17:48:20使用场景: 因为系统控件已经封装好了,而我们又需要自定义一些内容。 例如: ...等一些需要更改私有变量的控件 实现代码片段 Class<?> class1 = Class.forName("android...使用场景:
因为系统控件已经封装好了,而我们又需要自定义一些内容。
例如:
1、toolbar左边的setNavigationIcon我们需要自定义,做一动画效果,
2、recyclerView的滑动监听OnItemTouchListeners。
等一些需要更改私有变量的控件
实现代码片段
Class<?> class1 = Class.forName("android.support.v7.widget.Toolbar"); Field field = class1.getDeclaredField("mNavButtonView");//变量名称 mNavButtonView:是toolbar中的一个私有变量 field.setAccessible(true);//开放权限 mNavButtonView = (ImageButton) field.get(treeToolbar);//treeToolbar类实例
toolbar例子:获取左边的ImageView,设置为自己的帧动画
/** * 运行升级动画 */ public void runUpgradeAnim() { try { Class<?> class1 = Class.forName("android.support.v7.widget.Toolbar");//有时必须是路径形式,不能是.getClass()获得和class,可能原因获取是IDE缓存问题。 Field field = class1.getDeclaredField("mNavButtonView");//变量名称 field.setAccessible(true);//开放权限 mNavButtonView = (ImageButton) field.get(treeToolbar); //下面是自己的自定义操作 mNavButtonView.setImageResource(R.drawable.anim_upgrade); AnimationDrawable animationDrawable2 = (AnimationDrawable) mNavButtonView.getDrawable(); if (!animationDrawable2.isRunning()) { animationDrawable2.start(); } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
recyclerView例子:获取私有变量mOnItemTouchListeners,将之清除,重新设置新的
public void clearSwipe(Object object) { try { Class<?> recyclerViewClass = Class.forName("android.support.v7.widget.RecyclerView"); Field field = recyclerViewClass.getDeclaredField("mOnItemTouchListeners"); field.setAccessible(true); ArrayList<RecyclerView.OnItemTouchListener> mOnItemTouchListeners = (ArrayList<RecyclerView.OnItemTouchListener>) field.get(object); mOnItemTouchListeners.clear(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }
如此就可以封装成方法如下:
public static <T> T reflect(String clsPath, Objects instance, String reflectName) { try { return (T) reflect(Class.forName(cls), instance, reflectName); } catch (ClassNotFoundException e) { e.printStackTrace(); return null; } } public static <T> T reflect(Class<?> cls, Objects instance, String reflectName) { try { Field field = cls.getDeclaredField(reflectName); field.setAccessible(true); return (T) field.get(instance); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); return null; } } }
-
java/android 反射demo,通俗易懂,你值得拥有!!!
2016-11-06 20:15:52public class Student {// 变量和setAge、getAge方法都是私有的 private String id, name, sex; private int age; private final static String CLASSNAME = "Student";private void setAge(int age) { tpackage com.example;
public class Student {
// 变量和setAge、getAge方法都是私有的 private String id, name, sex; private int age; private final static String CLASSNAME = "Student"; private void setAge(int age) { this.age = age; } private void getAge() { System.out.println("age---" + age); } // test方法是公有 public void test(int i, int j) { System.out.println("result---" + (i + j)); }
}
package com.example;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;public class Test {
/** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub try { Class class1 = Class.forName("com.example.Student"); // 或者Class class1 = Student.class; // 获取所有的变量,包括私有 Field[] fields = class1.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { // System.out.println(fields[i].getType()); System.out.println(Modifier.toString(fields[i].getModifiers()) + " " + fields[i].getType().getSimpleName() + " " + fields[i].getName()); } // 获取所有的方法,包括私有 Method[] methods = class1.getDeclaredMethods(); StringBuilder parameterTypeBuilder; for (int i = 0; i < methods.length; i++) { parameterTypeBuilder = new StringBuilder(" ");// 为了美观,参数开始、结束加个空格 Class[] classes = methods[i].getParameterTypes(); for (int j = 0; j < classes.length; j++) {// 方法参数类型 if (classes.length > 1) { parameterTypeBuilder.append(classes[j].getSimpleName() + " "); } else { parameterTypeBuilder.append(classes[j].getSimpleName() + " "); } } boolean result = isEmpty(parameterTypeBuilder.toString()); System.out.println(Modifier.toString(methods[i].getModifiers()) + " " + methods[i].getReturnType().getSimpleName() + " " + methods[i].getName() + ((result) ? "()" : "(" + parameterTypeBuilder.toString() + ")")); parameterTypeBuilder = null; } // 调用私有属性 Student student = (Student) class1.newInstance();// 强转对象 Field ageField = class1.getDeclaredField("age"); ageField.setAccessible(true); ageField.set(student, 24);// 设置 age值 // 调用私有方法 Method getAgeMethod = class1.getDeclaredMethod("getAge"); getAgeMethod.setAccessible(true); getAgeMethod.invoke(student);// 调用getAge //调用私有方法setAge修改值,再打印 Method setAgeMethod = class1.getDeclaredMethod("setAge",int.class);// 调用setAge,该方法有参数 setAgeMethod.setAccessible(true); setAgeMethod.invoke(student,28);// 设置age getAgeMethod.invoke(student);// 调用getAge } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static boolean isEmpty(String text) { if ("".equals(text) || null == text) { return true; } return false; }
}
-
java/android中的反射机制
2017-09-04 09:46:17优点:增强代码的自适应能力(动态的创建对象)、调用一些类中的私有方法(例如通过反射机制调用android系统挂断电话的方法)。 缺点:降低程序性能。牛逼的背后总是苦逼,反射机制说白了就是通过类名去解释类,然后告诉...Ps:最近在研究热修复技术,其中用到了反射机制,所以复习一下,做个记录。
什么是反射机制
个人理解就是通过反编译获取类中所有的信息(包括:变量、方法、接口),供开发者利用。
优缺点
优点:增强代码的自适应能力(动态的创建对象)、调用一些类中的私有方法(例如通过反射机制调用android系统挂断电话的方法)。
缺点:降低程序性能。牛逼的背后总是苦逼,反射机制说白了就是通过类名去解释类,然后告诉jvm我们需要做什么,肯定比jvm执行固定代码要耗时耗资源。
常用的几个类
api文档中反射所用到的所有类
ps:这里不讲反射机制中的代理Proxy,因为水平有限,仅仅介绍下面几个类
Class:由虚拟机自动构建,表示正在运行的java程序中的类或接口(下面几个类对象基本都是通过Class类获取的)。
Method:从类中获取的方法,获取方法后通过method.invoke(…)执行
Field:从类中获取的成员变量
Constructor:从类中获取的构造方法
Array:处理通过返回获取的数组(测量长度、修改数组等等)
Modifier:获取的方法或变量的修饰符(method.getModifiers()获取,如:private,public..)
这几个类的api也很简单,基本通过方法名就能理解,不在赘述。
一个Demo讲解用法
Ps:本例通过反射Date类,实现获取当前时间,即:当前的毫秒数,同System.currentTimeMillis()效果一样
//获取Date类的运行时类,Class的获取方法有3种 //1. xxx.class() ; //2. xxx.forName("java.util.Date") ; //通过全类名 //3. XXX xxx = new XXX(); xxx.class() ; Class c = Date.class; //获取Date所有声明的方法包括private类型的,但不包括父类的方法 //可以通过 c.getMethods()---获取包括父类的所有public方法,但不包括private类型方法 Method[] ms = c.getDeclaredMethods(); for (Method m : ms) { //获取方法需要传入的参数 Type[] types = m.getGenericParameterTypes(); StringBuilder builder = new StringBuilder(); builder.append("("); for (Type type : types) { builder.append(type.toString() + ","); } int last = builder.lastIndexOf(","); if (last > 0) { builder.deleteCharAt(last); } builder.append(")"); //获取方法的修饰类型(private、public等) String modifier = Modifier.toString(m.getModifiers()) ; //获取方法的返回类型 String rType = m.getGenericReturnType().toString() ; System.out.println(modifier + " " + rType + " " + m.getName() + builder.toString()); }
通过上面的代码,可以获取Date类的所有方法,上图只截取了部分,其中有个用红色方框标记的方法,是私有的,通过源码可以知道,此方法可以得到当前时间的毫秒数,我们可以通过反射机制,调用这个方法,达到获取当前毫秒数的目的
Class c = Date.class; //通过Class实例化一个Date类对象 Object o = c.newInstance(); //通过上例红方框中的方法名,得到该方法的实例 Method m = c.getDeclaredMethod("getTimeImpl"); //设置jvm不检测此方法的访问权限(相当于暴力破除private) m.setAccessible(true); //调用getTimeImpl()方法 long l = (long) m.invoke(o, null); System.out.println("currentTime:" + System.currentTimeMillis()); System.out.println("getTimeImpl:" + l);
执行结果:
Ps:其实这个例子并没有什么实际意义,只简单说明java反射机制的一些作用,可以调用系统不对开发者开发的功能,如果用自己写的类演示,没有丝毫意义。
再说Array
Array是反射机制中对数组的操作
//我们获取TestArray类的所有成员变量,并修改data数组 public class TestArray { private String str ; public long time ; private int[] data = new int[]{1,2,3,4,5} ; public int[] getData(){ return data ; } } //获取TestArray类的所有成员变量,和获取Method基本一致,不在编写注释 Class c = TestArray.class; Field[] fields = c.getDeclaredFields() ; for (Field field : fields) { String mdf = Modifier.toString(field.getModifiers()) ; String type = field.getGenericType().toString() ; String name = field.getName() ; System.out.println(mdf+" "+type +" "+name); } //修改TestArray类中的data数组 //新建对象 TestArray ta = new TestArray() ; System.out.println("修改之前的第三个数:"+person.getData()[2]); //获取TestArray的Class Class c1 = ta.getClass() ; //获取data成员变量 Field m = c1.getDeclaredField("data") ; //抑制jvm检测访问权限 m.setAccessible(true); //回去data成员变量值 Object o = m.get(ta) ; //判断data是否为数组 if(o.getClass().isArray()){ //打印数组长度 System.out.prinln("数组长度:"+Array.getLen(o)) ; //反射机制中,用Array类完成对反射数组的操作,将data数组中的第三个数改为77 Array.set(o,2,77); } System.out.println("修改之后的第三个数:"+person.getData()[2]);
结果:
android中2个反射机制的应用实例
android中对反射机制应用非常广泛,比如:热修复、电话挂断。
热修复:通过反射机制将生成的补丁”dex”,插入到DexPathList类的private Element[] dexElements数组的最前端,是系统查找类的时候,先找到补丁”dex”中的类,从而实现热修复的效果。ps:DexPathList是不对开发者开发的,连实例对象都获取不了,只能通过反射机制做到。
电话挂断:通过android系统源码可知道,挂断电话需要调用ITelephony类的endCall()方法,系统是不对我们开放的,所有也需要通过发射机制调用endCall方法。\
热修复中用到的反射机制代码,会在研究热修复的时候贴出,而反射机制挂断电话,网上有太多例子,这里就不做搬运工了。
-
android 中的反射机制和java的对比
2016-08-14 11:42:38本文介绍 android 反射和实现原理 ...方法获取变量的值,即使方法或属性是私有的的也可以通过反射的形式调用,这种“看透class”的能力被称为内省,这种能力在框架开发中尤为重要。有些情况下,我们要使用的 -
反射和注解在android开发中的应用
2019-06-18 17:06:28比如一个类的构造,属性,普通方法为私有的情况下,或者某些方法虽然不是私有的方法但是是被隐藏的方法,我们就需要使用反射才能获得他们。一般使用Class类来完成反射,这个类把成员变量划分为Filed区域,把构造划分... -
Java反射全解析(使用、原理、问题、在Android中的应用)
2021-01-19 13:55:49无法直接操作某个对象的变量和方法,比如私有方法,私有变量。 需要hook系统逻辑,比如修改某个实例的参数。 等等情况。 所以我们就需要一种机制能让我们去操作任意的类和对象。 这种机制,就是反射 -
IOC反射注解框架
2018-10-11 21:54:23IOC 反射注解框架 IOC 反射框架包含了java反射、注解(运行时)、Android相关的控件注入等 Java反射 在Android中反射无处不在,当我们观看Android源码的时候,你就会...注意: 在反射私有的时候,需要设置set... -
关于反射(一)
2016-11-30 15:05:59使用反射获取私有变量,大致分为以下几个步骤。1.获取Field在这之前,我们得先获取class对象,当然这很容易,任何类getClass()就可以了,之后我们可以通过(1).getDeclaredField(String)(获取所有field,包括私有的... -
一文了解JAVA反射(超详尽!)
2020-12-21 09:46:13反射是框架设计的灵魂,只有学好了反射,才能设计出好的...获取某些类的一些变量,调用某些类的私有方法.(举个栗子,例如在Android开发中我们可以用来开启WiFi热点,调用WifiManager中的setWifiApEnabled()方法) 增加代码 -
Android选项卡置底的方法
2012-11-10 10:11:48发现很多Android应用的选项卡 都是显示在页面底部的,网上有资料:通过反射获取TabWidget中的私有变量,改变其值。今天反编译了腾讯微薄,发现实现这个很简单,只需将布局文件中标签加个android:layout_gravity=... -
java 反射机制
2010-08-01 15:26:001、通过java反射机制,可以访问... 2、访问android SDK中私有方法和成员变量 3、批量出处理类成员,如R类。这里有一个很好的例子:http://www.huangzhimin.com/entries/151-error-invalid-result-data -
Android 自动连接蓝牙
2018-12-20 14:29:30蓝牙是手机和智能硬件通信常用的方式,蓝牙通信可分为传统蓝牙和低功耗蓝牙(BLE)。其中BLE的连接断开等操作可以通过Android SDK中...我们可以利用反射调用Android中的私有API进行连接断开操作。 0x01 声明变量 ... -
android 选项卡(TabHost) 置底
2011-12-05 07:45:39摘要:发现很多微薄如腾讯,新浪的选项卡都是显示在页面底部的,网上有资料:通过反射获取TabWidget中的私有变量,改变其值。今天反编译了腾讯微薄,发现实现这个很简单,只需将布局文件中标签加个android:layout_... -
Android初级——Reflect简单使用
2017-07-29 21:47:40Android初级——Reflect...如果一个类当中的变量和方法为私有时,我们在其它地方就无法通过新建这个类的实例来获取它,这时候就可以采用Reflect(反射)机制来解决这个问题。通过反射我们能够获取某个类中的私有成员。 -
【转】Android选项卡置底的方法
2015-01-04 09:34:00发现很多Android应用的选项卡 都是显示在页面底部的,网上有资料:通过反射获取TabWidget中的私有变量,改变其值。今天反编译了腾讯微薄,发现实现这个很简单,只需将布局文件 中<TabWidget />标签加个android:... -
android 选项卡(TabHost) 置底
2011-07-27 09:12:41摘要:发现很多微薄如腾讯,新浪的选项卡都是显示在页面底部的,网上有资料:通过反射获取TabWidget中的私有变量,改变其值。今天反编译了腾讯微薄,发现实现这个很简单,只需将布局文件中<TabWidget/>... -
黑马程序员- 枚举和反射
2013-06-01 14:08:09------- android培训、java培训、期待与您交流! ---------- l枚举就相当于一个类,其中也可以定义构造方法、成员变量、普通方法和抽象方法。 l枚举元素必须位于枚举体中的最开始部分,枚举元素... -
黑马程序员_反射、枚举
2012-11-10 04:03:08---------------------- android培训、java培训、期待与您交流! ---------------------- 枚举 枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。枚举可以让... -
黑马程序员__反射基础
2013-07-23 10:28:53Android开发、java培训、期待与您交流! ---------------------- 枚举类: JDK1.5新特性 枚举是一个特殊的类,枚举中的元素相当于类的实例对象,其中可以定义构造方法,成员变量,普通方法和抽象方法。定义构造... -
黑马程序员---枚举与反射
2013-12-06 01:41:22android培训、java培训、期待与您交流! ---------------------- 一、枚举 1、 用普通类如何实现枚举功能,定义一个Weekday类,模拟枚举功能。 (1)定义一个私有构造函数。 (2)每一个类分别... -
枚举,享元模式,反射基础
2013-03-18 22:56:47------- android培训、java培训、期待与您交流! ---------- 枚举类: JDK1.5新特性 枚举是一个特殊的类,枚举中的元素相当于类的实例对象,其中可以定义构造方法,成员变量,普通方法和抽象方法。定义构造方法时... -
黑马程序员________Java高新技术之反射机制及枚举注释
2012-10-17 09:36:26------- android培训、java培训、期待与您交流! ---------- ... 枚举就是要让某个类型的变量的取值...首先在枚举内私有他的构造方法,每个元素分别用一个公有的静态成员变量表示变量表示。然后定义若干公有方法 -
黑马程序员--Java基础加强--07枚举、反射、注释
2014-03-23 11:08:09----------------------Android培训、Java培训、java学习型技术博客、期待与您交流! ---------------------- 枚举 枚举:枚举是一种特殊的类,其中每个元素都是该类的一个实例对象。 作用:就是要让某一个... -
tabWidget去除系统默认白色底角
2012-05-10 15:34:16for (int i = 0; i < tabWidget.getChildCount(); i++) { /** * 此方法是为了去掉系统默认的色白的底角 在 TabWidget中... * 都是私有变量,但是我们可以通过反射来获取 由于还不知道Android 2.2的接口是... -
10.java之父被B站学习者下载达7000万次的Java视频教程你还没有看过知乎
2020-10-21 11:03:44反射是框架设计的灵魂,只有学好了反射,才能设计出好的框架 一.反射的概述Java反射机制是在运行状态...) 反射的作用获取某些类的一些变量,调用某些类的私有方法.(举个栗子,例如在Android开发中我们可以用来开启WiFi热点
-
算法导论(基础知识)——编程大牛的必经之路
-
微波学习:S参数
-
数字电视业务信息及其编码.zip
-
net start.docx
-
PHP支付宝微信支付配置教程
-
转行做IT-第5章 流程控制语句
-
【Rsyslog】V 8.2008支持的模块
-
labview 经典实例.zip
-
TF-IDF算法
-
第1章 Java入门基础及环境搭建【java编程进阶】
-
反向传播aaaaaaaaaaaaaaa.rar
-
Demo.unitypackage
-
Unity游戏开发之数字华容道
-
idea 修改远程 git仓库地址到阿里云code 推送
-
智能健康建筑白皮书(2021).pdf
-
wx-cms-template-master.zip
-
转行做IT-第2章 HTML入门及高级应用
-
【数据分析-随到随学】Tableau数据分 析+PowerBI
-
日志处理-01
-
彻底卸载MySQL.txt