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的一段代码:
- 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,是被@hide标注的。
被@hide注解的类和方法就是私有API。
假设一个应用想调用这些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) { }
Java反射及其在Android中的应用学习总结的更多相关文章
- Java 反射在实际开发中的应用
运行时类型识别(RTTI, Run-Time Type Information)是Java中非常有用的机制,在java中,有两种RTTI的方式,一种是传统的,即假设在编译时已经知道了所有的类型:还有一 ...
- java反射查看jar包中所有的类名方法名
不反编译,不用其他工具,用java反射查看jar包中所有的类名方法名,网上很多都报错,下面这个你试试看:话不多说直接撸代码: import java.lang.reflect.Field; impor ...
- [转]Java 反射在实际开发中的应用
一:Java类加载和初始化 1.1 类加载器(类加载的工具) 1.2 Java使用一个类所需的准备工作 二:Java中RTTI 2.1 :为什么要用到运行时类型信息(就是RTTI) 2.2 :RTT ...
- Java时间间隔问题在Android中的使用
转载请注明出处:http://www.cnblogs.com/cnwutianhao/p/6606720.html 假设我们在做项目的时候,获取到了一段音频,也知道音频长度,那么我们想对音频做一些处理 ...
- Java:类集框架中集合的学习
Java:类集框架中集合的学习 集合 Java:Set的学习 Set是类集框架中的集合类.集合是不按特定的方式排序,并且没有重复对象的一种类. Q:Set如何操作?Set中的不按特定方式排序是怎么排序 ...
- 反射技术在Android中的应用
本博客转自:http://blog.csdn.net/tiefeng0606/article/details/51700866 动态语言: 一般认为在程序运行时,允许改变程序结构或变量类型,这种语言称 ...
- Java乔晓松-android中调用系统拍照功能并显示拍照的图片
android中调用系统拍照功能并显示拍照的图片 如果你是拍照完,利用onActivityResult获取data数据,把data数据转换成Bitmap数据,这样获取到的图片,是拍照的照片的缩略图 代 ...
- Java乔晓松-android中获取图片的缩略图(解决OutOfMemoryError)内存溢出的Bug
由于android获取图片过大是会出现内存溢出的Bug 07-02 05:10:13.792: E/AndroidRuntime(6016): java.lang.OutOfMemoryError 解 ...
- Java乔晓松-android中上传图片到服务器Tomcat(Struts2)
在做android开发的时候,有时你会用到图片的上传功能,在我的android项目中,我是选中图片,点击上传多张图片 android客户端上传图片部分的代码如下: package com.exampl ...
随机推荐
- [error:没有解析库]Couldn't find a tree builder with the features you requested: xml. Do you need to install a parser library?
将代码拷贝到服务器上运行,发生错误提示需要新安装parser library. 查看代码中发现有以下内容: soup = BeautifulSoup(open(fp), 'xml') 安装解析库即可: ...
- Hadoop全分布式模式安装
一.准备 1.准备至少三台linux服务器,并安装JDK 关闭防火墙如下 systemctl stop firewalld.service systemctl disable firewalld.se ...
- Model View Controller(MVC) in PHP
The model view controller pattern is the most used pattern for today’s world web applications. It ha ...
- DS博客作业——树
DS博客作业--树 1.本周学习总结 1.思维导图 2.谈谈你对树结构的认识及学习体会. 在树这一章节,我们学习的是二叉树的算法. 树的构建:一种是直接给树的顺序存储结构的字符串,一种是通过先序遍历和 ...
- [JLOI2011]飞行路线 (分层图,最短路)
题目链接 Solution 建立 \(k+1\) 层图跑 \(Dijkstra\) 就好了. Code #include<bits/stdc++.h> #define ll long lo ...
- javaweb学习总结(十)——HttpServletRequest对象(一)(转)
(每天都会更新至少一篇以上,有兴趣的可以关注)转载自孤傲苍狼 一.HttpServletRequest介绍 HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器 ...
- 一个老忘且非常有用的jquery动画方法 网页上卷
$('html,body').animate({scrollTop:800+'px'},500) //网页上卷800像素 在半秒之内
- PHP读取APK的包信息,包括包名,应用名,权限,LOGO等
[转]PHP读取APK的包信息,包括包名,应用名,权限,LOGO等 声明本文转自: 原文链接:https://www.jb51.net/article/53780.htm: 感谢分享! <?ph ...
- Group by 两表联查取另一表与之关联数据的总数
使用group by 需要查询的字段 必须要放在group by 后面 SELECT U.UserLotterySn,count(W.Userlotterysn) as WinCount,U.Acti ...
- AC日记——花店橱窗布置 codevs 1028
题目描述 Description 假设以最美观的方式布置花店的橱窗,有F束花,V个花瓶,我们用美学值(一个整数)表示每束花放入每个花瓶所产生的美学效果.为了取得最佳的美学效果,必须使花的摆放取得最大的 ...