一. Java反射机制
Reflection 是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例如Object)、实现之interfaces(例如Serializable),也包括fields和methods的所有信息,并可于运行时改变fields内容或调用methods(包括被声明为private的field和method)。
二. 打印一个类的信息Demo
可以写一个Utils类来打印一个类的信息:
ReflectUtils.java
package com.example.test;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.lang.reflect.Type;public class ReflectUtils { // 要打印的类 private Class classTobePrint;// 单例模式 private static ReflectUtils reflectUtils; private ReflectUtils(){ } public static ReflectUtils getInstance(){ if ( reflectUtils == null ) { synchronized (ReflectUtils.class) { if ( reflectUtils == null ) { reflectUtils = new ReflectUtils(); } } } return reflectUtils; } public ReflectUtils setClass(Class<?> c){ this.classTobePrint = c; return reflectUtils; } public ReflectUtils setClass(String className) throws ClassNotFoundException { this.classTobePrint = getClass(className); return reflectUtils; }// 打印输出类的所有信息 public void listAllInfo() throws ClassNotFoundException { if ( classTobePrint == null ) { return ; } // 要打印的类 Class cc = classTobePrint; // 输出父类名 getSuperClassName(cc); // 输出接口名 getInterfaceInfo(cc); // 输出构造函数 getConstructInfo(cc.getDeclaredConstructors()); // 输出域 getFildInfo(cc.getDeclaredFields()); // 输出方法 getMethodsInfo(cc.getDeclaredMethods()); // 输出内部类 getInerclassInfo(cc.getDeclaredClasses()); // 输出类加载器 getClassLoaderInfo(cc); // 复位classTobeTest classTobePrint = null; } /** * 输出父类名 */ public void getSuperClassName(Class<?> c) { System.out.println("\n父类"); // Class<?> superClass = c.getSuperclass();// System.out.println(superClass.getName()); Type t = c.getGenericSuperclass(); if (t==null) { System.out.println("无父类"); } System.out.println(t); } /** * 取得类实现的接口,因为接口类也属于Class,所以得到接口中的方法也是一样的方法得到哈 */ public void getInterfaceInfo(Class<?> c) { Class<?> interfaces[] = c.getInterfaces(); System.out.println("\n接口"); if (interfaces.length == 0) { System.out.println("无接口"); return; } for (Class<?> class1 : interfaces) { System.out.println(class1.getName()); } } /** * 输出类的包名 传入类 , 如 传入 User.class */ public void getPackageName(Class<?> c) { System.out.println("\n包名"); System.out.println(c.getPackage()); } /** * 输出类的完整类名 传入类, 如 传入 User.class */ public void getName(Class<?> c) { System.out.println("\n完整类名"); System.out.println(c.getName()); } /** * 输出对象的类的包名 传入对象 */ public void getPackageName(Object object) { System.out.println("\n包名"); System.out.println(object.getClass().getPackage()); } /** * 输出对象的类的完整类名 传入对象 */ public void getName(Object object) { System.out.println("\n完整类名"); System.out.println(object.getClass().getName()); } /** * 得到一个类的类型 传入完整类名,如 "cn.lee.demo.Person" * * @throws ClassNotFoundException */ public Class<?> getClass(String className) throws ClassNotFoundException { Class<?> c = Class.forName(className); return c; } /** * 输出构造函数 */ public void getConstructInfo( @SuppressWarnings("rawtypes") Constructor[] cons) { System.out.println("\n构造函数"); if (cons.length == 0) { System.out.println("无构造函数"); return; } for (Constructor<?> con : cons) { // 打印修饰符 int mo = con.getModifiers(); System.out.print(Modifier.toString(mo)); // 打印构造函数名 System.out.print(" " + con.getName()); // 输出参数; getParmsInfo(con.getParameterTypes()); System.out.println(); } } /** * 输出所有域 (成员) 传入 Field[] fields = class1.getDeclaredFields(); */ public void getFildInfo(Field[] fields) { System.out.println("\n域(成员)"); if (fields.length == 0) { System.out.println("无域(成员)"); return; } for (Field field : fields) { int m = field.getModifiers(); System.out.print(Modifier.toString(m) + " "); System.out.print(field.getType() + " "); System.out.println(field.getName()); } } /** * 输出所有方法 传入Method[] methods = class1.getDeclaredMethods(); */ public void getMethodsInfo(Method[] method) { System.out.println("\n方法"); if (method.length == 0) { System.out.println("无方法"); return; } for (Method mt : method) { int m = mt.getModifiers(); // 修饰符 System.out.print(Modifier.toString(m) + " "); // 输出返回类型 System.out.print(mt.getReturnType()); System.out.print(" " + mt.getName()); getParmsInfo(mt.getParameterTypes()); } } /** * 输出方法里的参数的信息 */ public void getParmsInfo(@SuppressWarnings("rawtypes") Class[] parm) { System.out.print(" ("); for (Class<?> c : parm) { System.out.print(c.getName() + " "); } System.out.print(")"); System.out.println(); } /** * 输出内部类 */ public void getInerclassInfo( @SuppressWarnings("rawtypes") Class[] innerClass) { System.out.println("\n内部类"); if (innerClass.length == 0) { System.out.println("无内部类"); return; } for (@SuppressWarnings("rawtypes") Class c : innerClass) { System.out.println(c.getName() + "{"); getMethodsInfo(c.getDeclaredMethods()); System.out.println("}"); } } /** * 输出类加载器的信息 * 在java中有三种类类加载器。[这段资料网上截取] * * 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。 * * 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类 * * 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。 * */ public void getClassLoaderInfo(Class<?> c) { System.out.println("\n类加载器"); System.out.println(c.getClassLoader().getClass().getName()); }}
ReflectUtils.getInstance().setClass("android.util.Log").listAllInfo();
得到的打印结果:
08-18 22:14:56.890: I/System.out(1208): 父类08-18 22:14:56.930: I/System.out(1208): class java.lang.Object08-18 22:14:56.930: I/System.out(1208): 接口08-18 22:14:56.930: I/System.out(1208): 无接口08-18 22:14:56.930: I/System.out(1208): 构造函数08-18 22:14:56.930: I/System.out(1208): private android.util.Log ()08-18 22:14:56.930: I/System.out(1208): 域(成员)08-18 22:14:56.930: I/System.out(1208): public static final int ASSERT08-18 22:14:56.930: I/System.out(1208): public static final int DEBUG08-18 22:14:56.940: I/System.out(1208): public static final int ERROR08-18 22:14:56.940: I/System.out(1208): public static final int INFO08-18 22:14:56.940: I/System.out(1208): public static final int LOG_ID_EVENTS08-18 22:14:56.940: I/System.out(1208): public static final int LOG_ID_MAIN08-18 22:14:56.940: I/System.out(1208): public static final int LOG_ID_RADIO08-18 22:14:56.940: I/System.out(1208): public static final int LOG_ID_SYSTEM08-18 22:14:56.940: I/System.out(1208): public static final int VERBOSE08-18 22:14:56.940: I/System.out(1208): public static final int WARN08-18 22:14:56.950: I/System.out(1208): private static interface android.util.Log$TerribleFailureHandler sWtfHandler08-18 22:14:56.950: I/System.out(1208): 方法08-18 22:14:56.950: I/System.out(1208): public static int d (java.lang.String java.lang.String )08-18 22:14:56.960: I/System.out(1208): public static int d (java.lang.String java.lang.String java.lang.Throwable )08-18 22:14:56.960: I/System.out(1208): public static int e (java.lang.String java.lang.String )08-18 22:14:56.960: I/System.out(1208): public static int e (java.lang.String java.lang.String java.lang.Throwable )08-18 22:14:56.960: I/System.out(1208): public static class java.lang.String getStackTraceString (java.lang.Throwable )08-18 22:14:56.960: I/System.out(1208): public static int i (java.lang.String java.lang.String )08-18 22:14:56.960: I/System.out(1208): public static int i (java.lang.String java.lang.String java.lang.Throwable )08-18 22:14:56.960: I/System.out(1208): public static native boolean isLoggable (java.lang.String int )08-18 22:14:56.970: I/System.out(1208): public static int println (int java.lang.String java.lang.String )08-18 22:14:56.970: I/System.out(1208): public static native int println_native (int int java.lang.String java.lang.String )08-18 22:14:56.970: I/System.out(1208): public static interface android.util.Log$TerribleFailureHandler setWtfHandler (android.util.Log$TerribleFailureHandler )08-18 22:14:56.970: I/System.out(1208): public static int v (java.lang.String java.lang.String )08-18 22:14:56.980: I/System.out(1208): public static int v (java.lang.String java.lang.String java.lang.Throwable )08-18 22:14:56.980: I/System.out(1208): public static int w (java.lang.String java.lang.String )08-18 22:14:56.980: I/System.out(1208): public static int w (java.lang.String java.lang.String java.lang.Throwable )08-18 22:14:56.980: I/System.out(1208): public static int w (java.lang.String java.lang.Throwable )08-18 22:14:56.980: I/System.out(1208): static int wtf (int java.lang.String java.lang.String java.lang.Throwable boolean )08-18 22:14:56.980: I/System.out(1208): public static int wtf (java.lang.String java.lang.String )08-18 22:14:56.980: I/System.out(1208): public static int wtf (java.lang.String java.lang.String java.lang.Throwable )08-18 22:14:56.980: I/System.out(1208): public static int wtf (java.lang.String java.lang.Throwable )08-18 22:14:56.980: I/System.out(1208): public static int wtfStack (java.lang.String java.lang.String )08-18 22:14:56.980: I/System.out(1208): 内部类08-18 22:14:56.980: I/System.out(1208): android.util.Log$TerribleFailureHandler{08-18 22:14:56.990: I/System.out(1208): 方法08-18 22:14:57.000: I/System.out(1208): public abstract void onTerribleFailure (java.lang.String android.util.Log$TerribleFailure )08-18 22:14:57.000: I/System.out(1208): }08-18 22:14:57.000: I/System.out(1208): android.util.Log$TerribleFailure{08-18 22:14:57.000: I/System.out(1208): 方法08-18 22:14:57.000: I/System.out(1208): 无方法08-18 22:14:57.000: I/System.out(1208): }08-18 22:14:57.010: I/System.out(1208): 类加载器08-18 22:14:57.010: I/System.out(1208): java.lang.BootClassLoader
三. Java反射操作域和方法的Demo
先写一个要被进行演示操作的类User.java
package com.yjq.reflect;import java.io.Serializable;import com.yjq.reflect.UserDescribtion.Sex;public class User implements Serializable{ private int id; private String name; private Sex sex; public User(){ super(); } public User(int _id,String _name,Sex _sex){ this.id=_id; this.name=_name; this.sex=_sex; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Sex getSex() { return sex; } public void setSex(Sex sex) { this.sex = sex; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", sex=" + sex + "]"; } public void test(){ testMethod(1,"hello");} private void testMethod(int i,String s){ System.out.println("private method in user "+i+s); }public enum Sex { MALE("男"), FEMALE("女"); // 枚举对象的属性 private String sexDescribtion; // 枚举对象构造函数 private Sex(String sx) { this.sexDescribtion = sx; }}}Demo:
// 通过Java反射调用方法 private void callMethodsDemo() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { Class<?> class1 = null; class1 = Class.forName("com.yjq.reflect.User"); System.out.println("\nDemo: \n调用无参方法testMethod():"); Method method = class1.getDeclaredMethod("testMethod", new Class[]{int.class, String.class});// .getMethod("test"); getMethod只能调用public的方法 method.setAccessible(true); method.invoke(class1.newInstance(),23,"hello23"); System.out.println("调用有参方法setId(int):"); method = class1.getMethod("setId",int.class); User user = (User)class1.newInstance(); method.invoke(user,100); System.out.println(user); } // 通过Java反射操作域(成员) private void setFieldsDemo() throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchFieldException, SecurityException { Class<?> class1 = null; class1 = Class.forName("com.yjq.reflect.User"); Object obj = class1.newInstance(); // 须有无参构造函数 Field userNameField = class1.getDeclaredField("name"); userNameField.setAccessible(true); userNameField.set(obj, "==Myname=="); System.out.println("Demo: 通过Java反射操作域(成员): 修改属性之后得到属性变量的值:" + userNameField.get(obj)); } // 通过java反射创建对象 private void getInstanceDemo() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException { User user1 = null; User user2 = null; Class<?> class1 = Class.forName("com.yjq.reflect.User"); // 得到一系列构造函数集合 Constructor<?>[] constructors = class1.getConstructors(); user1 = (User) constructors[0].newInstance(); user1.setId(112031); user1.setName("leeFeng"); user2 = (User) constructors[1].newInstance(12432, "Mali", Sex.FEMALE); System.out.println("Demo:通过java反射创建对象"); System.out.println(user1); System.out.println(user2); }
四. Java反射在android中的应用
摘自:http://mysuperbaby.iteye.com/blog/1458966
在Android中,可以从下面两点考虑来使用Java反射(Java Reflection)机制,从而达到意想不到的效果。这里也将展示Google是怎样在自己的应用中来使用Java反射机制的。
1. 同时兼容新老版本的SDK
Android往往会在新版本中引入一些新的API来替代老的API,这些新的API在性能或者易用性上比老的API更好。但为了兼容性,新老API往往是共存的。
在这种情况下,你的应用如果调用了新的API,是没办法在安装老版本Android的设备上运行的,但如果使用老的API,又没办法在安装新版本Android的设备上体现新API的性能。
这时候,就可以使用Java反射机制,从而实现一个apk,如果安装在老版本Android的设备上,则调用老的API;安装在新版本Android的设备上,则调用新的API。
下面是来自Google的一段代码:
- public class SharedPreferencesCompat {
- private static final Method sApplyMethod = findApplyMethod();
- private static Method findApplyMethod() {
- try {
- return SharedPreferences.Editor.class.getMethod("apply", new Class[0]);
- } catch (NoSuchMethodException e) {
- return null;
- }
- }
- public static void apply(SharedPreferences.Editor editor) {
- if (sApplyMethod != null) {
- try {
- sApplyMethod.invoke(editor, new Object[0]);
- return;
- } catch (IllegalAccessException e) {
- } catch (InvocationTargetException e) {
- }
- }
- editor.commit();
- }
- }
2. 使用私有的API
如果在Eclipse上开发应用,必须调用对应的Android SDK的标准API,即在开发文档中说明的API。调用非标准的即私有的API,是编译不过的。
但Android实际上有很多API,[email protected]@[email protected]??用这些API,则只有在编译整个系统image的时候才能编译过,而在Eclipse上是编译不过的。所以,这些API往往会被手机开发商的本地应用调用,则第三方的应用是没办法调用的。
这种情况下,可以使用Java反射机制来调用这些私有的API。一旦编译通过生成了apk,就能正常在手机上运行,因为这样的API的实现已经在手机系统中只是没有公开出来。
下面是来自Google的一段代码:
- private static final String AMR_INPUT_STREAM_CLASS = "android.media.AmrInputStream";
- private static Class<?> getAmrInputStreamClass() throws ClassNotFoundException {
- return Class.forName(AMR_INPUT_STREAM_CLASS);
- }
- private static InputStream createAmrInputStream(InputStream in) {
- try {
- Class<?> clazz = getAmrInputStreamClass();
- Constructor<?> constructor = clazz.getConstructor(new Class[] { InputStream.class });
- return (InputStream)constructor.newInstance(new Object[] { in });
- }
- ...
- }
3.补充:将SharedPreferences数据文件存储到sd卡上?
SharedPreference原则上只能保存在当前应用程序私有的shared_prefs目录中,不过可以利用反射技术改变系统内定的文件保存路径。try { Field field = ContextWrapper.class.getDeclaredField("mBase"); field.setAccessible(true); Object obj = field.get(this); field = obj.getClass().getDeclaredField("mPreferencesDir"); field.setAccessible(true); File file = new File("/sdcard/"); field.set(obj, file); SharedPreferences mySharedPreferences = getSharedPreferences("config", Activity.MODE_PRIVATE); SharedPreferences.Editor editor = mySharedPreferences.edit(); editor.putString("name", "nancy"); editor.commit();} catch (Exception e) { }
版权声明:本文为博主原创文章,未经博主允许不得转载。