参考博客:http://www.cnblogs.com/crazypebble/archive/2011/04/13/2014582.htmlhttp://gqdy365.iteye.com/blog/2124969?utm_source=tuicoolhttp://blog.csdn.net/yq6073025/article/details/52782257反射的作用
可以利用反射机制在java程序中,动态的去调用一些PRotected甚至是private的方法或类,然后可以在很大程度上满足我们的一些比较特殊需求。
实现反射的方法
先创建一个对象实例
方法1:
Class<?> cls=Class.forName(包名);
Person p=(Person)cls.newInstance();
p.setAge(20);
方法2:
Person p = new Person();Class<?> cls=p.getClass();Person p2=(Person)cls.newInstance();
p.setAge(20);
方法3:
Class<?> cls=Person.Class();
Person p=(Person)cls.newInstance();//强制转换p.setAge(20);
那么知道了反射机制如何生成类对象,之后就要开始调用类的方法了
Class<?>cls=Class.forName(包名); cls对象 可调用方法如下
| 方法关键字 | 含义 |
|---|---|
| getDeclareMethods() | 获取所有的方法 |
| getReturnType() | 获取方法的返回值类型 |
| getParameterTypes() | 获取方法的传入参数类型 |
| getDeclareMethod("方法名,参数类型.class,....") | 获得特定的方法 |
| - | |
| 构造方法关键字 | 含义 |
| getDeclaredConstructors() | 获取所有的构造方法 |
| getDeclaredConstructors(参数类型.class,....) | 获取特定的构造方法 |
| - | |
| 成员变量 | 含义 |
| getDeclaredFields | 获取所有成员变量 |
| getDeclaredField(参数类型.class,....) | 获取特定的成员变量 |
| - | |
| 父类和父接口 | 含义 |
| getSuperclass() | 获取某类的父类 |
| getInterfaces() | 获取某类实现的接口 |
package com.zwq.test; public abstract class Person { String name = ""; private int age = 0; public int fPubVar = 0; abstract void getPhone(); public Person() { System.out.println("I am Farther"); } int myAge() { return 50; } String myName() { return "Father"; } public void callSun() { getPhone(); priMethod(25); } private void priMethod(Integer a) { age = a; System.out.println("I am priMethod , Dont call me! age " + age); } /** * @hide */ public void hideMethod(String name) { System.out.println("I am hideMethod , Dont call me! name:" + name + " age:" + age); } } Java代码
package com.zwq.test; import java.util.Observable; import java.util.Observer; public class Man extends Person implements Observer { private int age = 0; private String var1 = "I am var1"; public int var2 = 20; public Man() { System.out.println("I am Man" + var1); age = 20; } public int myAge() { return 28; } public String myName() { return "Jerome"; } private void getName(){ System.out.println("I am Jerome"); } /** *@hide */ private void getAge(){ System.out.println("I am "+age); } @Override void getPhone() { System.out.println("I am sun , My age is " + age + "___" + var2); } @Override public void update(Observable o, Object arg) { } } 以上两个类只是为了测试,不用关心具体实现代码,只要知道有private变量和方法,protected变量和方法,public变量和方法。重点在下面: 二、利用反射,调用上面的类: Java代码
package com. zwq.test; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Main { public static void main(String[] args) { getInfo(); callSpuerMethod(); callCurrentMethod(); callOtherMethod(); } static void getInfo() { Man r = new Man(); Class<?> temp = r.getClass(); try { System.out.println("反射类中所有公有的属性"); Field[] fb = temp.getFields(); for (int j = 0; j < fb.length; j++) { Class<?> cl = fb[j].getType(); System.out.println("fb:" + cl + "___" + fb[j].getName()); } System.out.println("反射类中所有的属性"); Field[] fa = temp.getDeclaredFields(); for (int j = 0; j < fa.length; j++) { Class<?> cl = fa[j].getType(); System.out.println("fa:" + cl + "____" + fa[j].getName()); } System.out.println("反射类中所有的方法"); Method[] fm = temp.getMethods(); for (int i = 0; i < fm.length; i++) { System.out.println("fm:" + fm[i].getName() + "____" + fm[i].getReturnType().getName()); } System.out.println("反射类中所有的接口"); Class<?>[] fi = temp.getInterfaces(); for (int i = 0; i < fi.length; i++) { System.out.println("fi:" + fi[i].getName()); } System.out.println("反射类中私有属性的值"); Field f = temp.getDeclaredField("var1"); //var1属性名 f.setaccessible(true); String i = (String) f.get(r); System.out.println(i); } catch (Exception e) { e.printStackTrace(); } } /** * 修复父类变量,调用父类方法 */ static void callSpuerMethod() { Man r = new Man(); try { // 修改私有变量; Field f = r.getClass().getSuperclass().getDeclaredField("age"); f.setAccessible(true); f.set(r, 20); // 调用私有方法,必须要用getDeclaredMethod,而不能用getMethod; Method mp = r.getClass().getSuperclass() .getDeclaredMethod("priMethod", Integer.class); mp.setAccessible(true); mp.invoke(r, 18); // 调用隐藏方法 Method m = r.getClass().getSuperclass() .getMethod("hideMethod", String.class); m.setAccessible(true); m.invoke(r, "Jerome"); } catch (Exception e) { e.printStackTrace(); } } /** * 修复子类变量,调用子类方法 */ static void callCurrentMethod() { Man r = new Man(); try { // 修改私有变量; Field f = r.getClass().getDeclaredField("age"); f.setAccessible(true); f.set(r, 20); // 调用私有方法,必须要用getDeclaredMethod,而不能用getMethod; Method mp = r.getClass().getDeclaredMethod("getName"); mp.setAccessible(true); mp.invoke(r); // 调用隐藏私有方法 Method m = r.getClass().getDeclaredMethod("getAge"); m.setAccessible(true); m.invoke(r); } catch (Exception e) { e.printStackTrace(); } } /** * 用Class.forName加载类及实例化 */ static void callOtherMethod() { try { // Class.forName(xxx.xx.xx) 返回的是一个类, .newInstance() 后才创建一个对象 // Class.forName(xxx.xx.xx) 的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段 Class<?> cl = Class.forName("com.zwq.test.Man"); Object r = cl.newInstance(); // 修改私有变量; Field f = cl.getDeclaredField("age"); f.setAccessible(true); f.set(r, 20); // 调用私有方法,必须要用getDeclaredMethod,而不能用getMethod; Method mp = cl.getDeclaredMethod("getName"); mp.setAccessible(true); mp.invoke(r); // 调用隐藏私有方法 Method m = cl.getDeclaredMethod("getAge"); m.setAccessible(true); m.invoke(r); } catch (Exception e) { e.printStackTrace(); } } } 三、最后贴一个Android里面的具体事例: Java代码
/** * 获得包的大小 * * @param pkgName * @throws Exception */ public void queryPacakgeSize(String pkgName) throws Exception { if (pkgName != null) { // 使用放射机制得到PackageManager类的隐藏函数getPackageSizeInfo PackageManager pm = getPackageManager(); // 得到pm对象 try { // 通过反射机制获得该隐藏函数 Method getPackageSizeInfo = pm.getClass().getDeclaredMethod( "getPackageSizeInfo", String.class, ipackageStatsObserver.class); // 调用该函数,并且给其分配参数 ,待调用流程完成后会回调PkgSizeObserver类的函数 getPackageSizeInfo.invoke(pm, pkgName, new PkgSizeObserver()); // 停止主线程让PackageStats对象获得数据 Thread.sleep(8); } catch (Exception ex) { // Log.e("TAG", "NoSuchMethodException") ; ex.printStackTrace(); throw ex;// 抛出异常 } } } 综上:反射机制通过void setAccessible(boolean flag)方法可以得到一个类的private或者protected的方法和属性,使用这些private或者protected的方法和属性。
新闻热点
疑难解答