Java反射及其在Android中的应用学习总结

一. 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 = new ReflectUtils();

	private ReflectUtils(){ }

	public static ReflectUtils getInstance(){
		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());
	}

}

在android中运行

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.Object
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): 构造函数
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 ASSERT
08-18 22:14:56.930: I/System.out(1208): public static final int DEBUG
08-18 22:14:56.940: I/System.out(1208): public static final int ERROR
08-18 22:14:56.940: I/System.out(1208): public static final int INFO
08-18 22:14:56.940: I/System.out(1208): public static final int LOG_ID_EVENTS
08-18 22:14:56.940: I/System.out(1208): public static final int LOG_ID_MAIN
08-18 22:14:56.940: I/System.out(1208): public static final int LOG_ID_RADIO
08-18 22:14:56.940: I/System.out(1208): public static final int LOG_ID_SYSTEM
08-18 22:14:56.940: I/System.out(1208): public static final int VERBOSE
08-18 22:14:56.940: I/System.out(1208): public static final int WARN
08-18 22:14:56.950: I/System.out(1208): private static interface android.util.Log$TerribleFailureHandler sWtfHandler
08-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的一段代码:

Java代码  

  1. public class SharedPreferencesCompat {
  2. private static final Method sApplyMethod = findApplyMethod();
  3. private static Method findApplyMethod() {
  4. try {
  5. return SharedPreferences.Editor.class.getMethod("apply", new Class[0]);
  6. } catch (NoSuchMethodException e) {
  7. return null;
  8. }
  9. }
  10. public static void apply(SharedPreferences.Editor editor) {
  11. if (sApplyMethod != null) {
  12. try {
  13. sApplyMethod.invoke(editor, new Object[0]);
  14. return;
  15. } catch (IllegalAccessException e) {
  16. } catch (InvocationTargetException e) {
  17. }
  18. }
  19. editor.commit();
  20. }
  21. }

2. 使用私有的API

假设在Eclipse上开发应用,必须调用相应的Android SDK的标准API,即在开发文档中说明的API。调用非标准的即私有的API,是编译只是的。

但Android实际上有非常多API,是被@hide标注的。

被@hide注解的类和方法就是私有API。

假设一个应用想调用这些API,则仅仅有在编译整个系统image的时候才干编译过,而在Eclipse上是编译只是的。

所以。这些API往往会被手机开发商的本地应用调用。则第三方的应用是没办法调用的。

这种情况下,能够使用Java反射机制来调用这些私有的API。一旦编译通过生成了apk,就能正常在手机上执行,由于这种API的实现已经在手机系统中仅仅是没有公开出来。

以下是来自Google的一段代码:

Java代码  

  1. private static final String AMR_INPUT_STREAM_CLASS = "android.media.AmrInputStream";
  2. private static Class<?

    > getAmrInputStreamClass() throws ClassNotFoundException {

  3. return Class.forName(AMR_INPUT_STREAM_CLASS);
  4. }
  5. private static InputStream createAmrInputStream(InputStream in) {
  6. try {
  7. Class<?> clazz = getAmrInputStreamClass();
  8. Constructor<?> constructor = clazz.getConstructor(new Class[] { InputStream.class });
  9. return (InputStream)constructor.newInstance(new Object[] { in });
  10. }
  11. ...
  12. }

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) { }
时间: 2024-11-05 02:29:54

Java反射及其在Android中的应用学习总结的相关文章

Java时间间隔问题在Android中的使用

转载请注明出处:http://www.cnblogs.com/cnwutianhao/p/6606720.html 假设我们在做项目的时候,获取到了一段音频,也知道音频长度,那么我们想对音频做一些处理的时候,在这个处理动作之前往往要做时间循环判断 已知:音频长度,并且还给出下面四个条件重试时间长度 = 音频长度 × 0.7 + 30秒第一次重试: 重试时间长度 x 0.15第二次重试: 重试时间长度 x 0.5第三次重试: 重试时间长度 x 1 上述的已知条件我们可以用下面这两段代码来实现: p

Java 反射在实际开发中的应用

运行时类型识别(RTTI, Run-Time Type Information)是Java中非常有用的机制,在java中,有两种RTTI的方式,一种是传统的,即假设在编译时已经知道了所有的类型:还有一种,是利用反射机制,在运行时再尝试确定类型信息. 本篇博文会结合Thinking in Java 的demo 和实际开发中碰到的例子,对Java反射和获取类型信息做总体上整理.文章主要分为三块: Java类加载和初始化 Java中RTTI Java利用反射获取运行时类型信息 一:Java类加载和初始

[转]Java 反射在实际开发中的应用

一:Java类加载和初始化 1.1 类加载器(类加载的工具) 1.2 Java使用一个类所需的准备工作 二:Java中RTTI 2.1 :为什么要用到运行时类型信息(就是RTTI) 2.2  :RTTI在运行时如何表示 2.3   :  Class对象 2.3 : RTTI形式总结: 三:Java利用反射获取运行时类型信息 3.1 : 获取的方式 3.2 :   动态代理 四: Java反射在实际开发中应用 4.1  :在web项目中创建统一的拦截层 4.2 : 用于webService服务 :

利用java反射实现tomcat运行中添加新类

个人博客地址:http://www.cnblogs.com/wdfwolf3/.转载注明出处,谢谢. Java 反射一个是可以获取程序在运行时刻的内部结构,二是在运行时刻对一个Java对象进行操作.主要用途有以下几点: 1.工厂模式:Factory类中用反射的话,添加了一个新的类之后,就不需要再修改工厂类Factory了 2.数据库JDBC中通过Class.forName(Driver)来获得数据库连接驱动 3.分析类文件:得到类中的方法等等,访问一些不能访问的变量或属性(破解别人代码). 之前

Android中的动画学习总结

android中动画可分为三种:帧动画,补间动画,和属性动画.其中属性动画是google推荐的,它可以实现前面两种动画的效果,运用起来更加灵活. 帧动画:顾名思义,就是一帧一帧的图片,快速播放形成的动画. 具体实现步骤如下: 第一:新建一个drawable资源 以animation-list 为根节点创建资源文件. 第二:给ImageView或者其他View设置关联drawable.可以作为background或者src. 第三:在java代码中,通过View.getBackground():或

java反射之遍历类中所有内部类及属性方法

package com.zr.entity; /** * 仅用于测试类,从实际项目中抽出来的 * @author zr * */ public class Constant { /** * 参数校验枚举类 * @author zr * */ public static enum ResultObjectType { //成功 SUCC(0), //失败,异常 ERROR(1), //参数错误 PARAMERROR(2), //数据为空 NODATA(9); private Integer val

Android利用Java反射机制修改Android System Language

private void updateLanguage(Locale locale) { try { Object objIActMag, objActMagNative; Class clzIActMag = Class.forName("android.app.IActivityManager"); Class clzActMagNative = Class.forName("android.app.ActivityManagerNative"); Method

java 反射机制与动态加载类学习要点

获取Class类的对象: 假设Foo是一个类,Foo foo = new Foo():则 第一种:Class c1 = Foo.class; 第二种:Class c2 = foo.getClass(); 第三种:Class c3 = Class.forName("com.nudt.reflection.Foo"); //会抛出异常 此时  c1 == c2 == c3 为true 也可以通过c1\c2\c3创建Foo的实例: Foo foo = (Foo)c1.newInstance(

Android中图表AChartEngine学习使用与例子

很多时候项目中我们需要对一些统计数据进行绘制表格,更多直观查看报表分析结果.基本有以下几种方法: 1:可以进行android  api进行draw这样的话,效率比较低 2:使用开源绘表引擎,这样效率比较高.下面就介绍一种. AChartEngine(简称ACE)是Google的一个开源图表库(for Android).它功能强大,支持散点图.折线图.饼图.气泡图.柱状图.短棒图.仪表图等多种图表. 该项目地址位于: http://code.google.com/p/achartengine/ 你