`
stephen830
  • 浏览: 2964644 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

实战java反射机制-让你迅速认识java强大的反射机制

    博客分类:
  • java
阅读更多
★★★ 本篇为原创,需要引用转载的朋友请注明:《 http://stephen830.iteye.com/blog/256723 》 谢谢支持! ★★★


Reflection 是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。
(这句话是引用台湾作家侯捷对反射机制描述的一个概念)

java的反射机制从java诞生之日起就成为java的一个重要特性。反射机制也是目前众多框架实现的一个基础。

反射,简单的讲就是根据给出的类的名称,我就可以获得这个类所有的信息(包括属性,构造器,方法等),同时还可以对类的方法进行调用。这在需要动态加载类的情况下尤其显得重要。

目前流行的大部分java框架(例如ssh等)的底层有很多都是基于反射机制来实现的。

从下面的实例中可以了解并学会关于java反射的一些基本特点:
(1)如何获得动态加载类的修饰符,包名,类名,使用的接口,继承的父类
(2)动态获取类的所有属性名,修饰符,属性类型
(3)动态获取所有定义的构造器,构造器使用的参数数量和参数类型
(4)动态获取所有方法,方法的返回值类型,方法名,方法参数数量,方法参数类型
(5)动态调用加载类的方法



下面就从一个例子来深入浅出的认识下java的反射机制:

/*
 * Created on 2005-6-12
 * Author stephen
 * Email zhoujianqiang AT gmail DOT com
 * CopyRight(C)2005-2008 , All rights reserved.
 */
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * java反射机制的测试类.
 * 
 * @author stephen
 * @version 1.0.0
 */
public class ReflectTest {
	
	/**
	 * 数组参数的标志字符和实际对应的类型.
	 * 其中'L'表示对象数组,其余表示java基础类型的数组.
	 */
	public static final char[]   CODES = new char[]
	{'Z',      'B',   'C',  'L','D',     'F',    'I',   'J',  'S'};
	public static final String[] VALUES =          
	{"boolean","byte","char","","double","float","int","long","short"};
	
	/**
	 * 解析方法的参数.
	 * @param parameter 待解析的参数.
	 * @return
	 */
	public static String parseParameter(String parameter) {
		/* 在java.lang.Class类中关于参数的说明补充
		 * ------------------------------------
		 * Examples:
	     * String.class.getName()
	     *     returns "java.lang.String"
	     * byte.class.getName()
	     *     returns "byte"
	     * (new Object[3]).getClass().getName()
	     *     returns "[Ljava.lang.Object;"
	     * (new int[3][4][5][6][7][8][9]).getClass().getName()
	     *     returns "[[[[[[[I"
	     * ------------------------------------
	     * 1个[表示1维数组,2个[表示2维数组,...,依此类推。
		 */
		boolean isArray = false;
		//如果是数组的可能会在最后带个分号过来,需要去掉.
		if(parameter.charAt(parameter.length()-1)==';'){
			//去掉最后的分号
			parameter = parameter.substring(0,parameter.length()-1);
		}
		while(parameter.indexOf('[')==0){
			isArray = true;
			parameter = parameter.substring(1)+"[]";
		}
		if(isArray){
			char code = parameter.charAt(0);
			for(int i=0;i<CODES.length;i++){
				if(CODES[i]==code){
					parameter=VALUES[i]+parameter.substring(1);
					break;
				}
			}
		}
		return parameter;
	}
	
	/**
	 * 解析属性的类型.
	 * @param parameter 待解析的属性.
	 * @return
	 */
	public static String parseFieldParameter(String parameter) {
		return parseParameter(parameter);
	}
	
	/**
	 * 解析方法返回值的类型.
	 * @param parameter 待解析的方法返回值类型.
	 * @return
	 */
	public static String parseMethodParameter(String parameter) {
		return parseFieldParameter(parameter);
	}
	

	/**
	 * main方法.
	 * @param args
	 */
	public static void main(String[] args) {
		try {
    		StringBuffer debugInfo = new StringBuffer();
    		
    		String className = "java.lang.StringBuffer";//填写要测试的类
			Class c = Class.forName(className);//载入类
			
			debugInfo.append("****************************************\n");
			debugInfo.append("*  "+className+" \n*  通过java反射机制取出的信息"+"\n");
			debugInfo.append("****************************************\n");
			
			//获取包和类名
			Package thePackage = c.getPackage();//获取类的包
			String[] names = c.getName().split("[.]");
			String name = names[names.length-1];
			//获取类的修饰符[如 public final private等等],
			//具体的含义请查看 [java.lang.reflect.Modifier] 中定义的修饰符常量
			//java.lang.String的修饰符是 public final
			int modifiers = c.getModifiers();
			debugInfo.append(Modifier.toString(modifiers)+" class "+ name);
			
			//取出类的父类(extends)
			Class superClass = c.getSuperclass();
			if(superClass!=null && (!"java.lang.Object".equals(superClass.getName()))){
				debugInfo.append(" extends ");
				debugInfo.append(superClass.getName());
			}
			
			//取出类的接口(implements)
			Class[] interfaces = c.getInterfaces();
			if(interfaces!=null && interfaces.length>0){
				debugInfo.append(" implements ");
				for(int i=0;i<interfaces.length;i++){
					if(i>0) debugInfo.append(",");
					debugInfo.append(interfaces[i].getName());
				}
			}
			
			debugInfo.append(" {\n");
			
			//取出所有定义的属性
			debugInfo.append("    //取出所有定义的属性\n");
			Field[] fields = c.getDeclaredFields();
			for(int i=0;fields!=null && i<fields.length;i++){
				//取出属性
				debugInfo.append("    "+Modifier.toString(fields[i].getModifiers())
						+" "+parseFieldParameter(fields[i].getType().getName())
						+" "+fields[i].getName());
				debugInfo.append(";\n");
			}
			
			//获取构造器方法
			debugInfo.append("    //取出所有的构造器方法\n");
			Constructor[] constructors = c.getConstructors();//取出所有定义的构造器方法
			for(int i=0;constructors!=null && i<constructors.length;i++){
				//取出构造器
				debugInfo.append("    "+Modifier.toString(constructors[i].getModifiers())
						+" "+name+"(");
				Class[] parameterTypes = constructors[i].getParameterTypes();
				for(int j=0;parameterTypes!=null&&j<parameterTypes.length;j++){
					if(j>0) debugInfo.append(",");
					debugInfo.append(parseParameter(parameterTypes[j].getName()));//构造器参数
				}
				debugInfo.append("){}\n");
			}
			
			//取出构造器以外的所有方法
			debugInfo.append("    //取出构造器以外的所有方法\n");
			Method[] methods = c.getDeclaredMethods();
			for(int i=0;methods!=null && i<methods.length;i++){
				//取出方法
				debugInfo.append("    "+Modifier.toString(methods[i].getModifiers())+" "
						+ parseMethodParameter(methods[i].getReturnType().getName()) +" "
						+methods[i].getName()+"(");
				Class[] parameterTypes = methods[i].getParameterTypes();
				for(int j=0;parameterTypes!=null&&j<parameterTypes.length;j++){
					if(j>0) debugInfo.append(",");
					debugInfo.append(parseParameter(parameterTypes[j].getName()));//构造器参数
				}
				debugInfo.append("){}\n");
			}
			debugInfo.append("}\n");
			
			System.out.println(debugInfo.toString()+"\n");//输出debug信息
			
			//利用反射机制来调用类中的方法
			//创建一个StringBuffer对象实例 相当于 StringBuffer o = new StringBuffer();
			Object o = c.newInstance();
			//调用方法 o.append(String):认识当参数为对象类型怎么调用的
			Class[] paramTypes = {Class.forName("java.lang.String")};//定义append方法需要的参数
			Object[] values = {new String("hello world")};//定义append方法需要的参数对应的数据
			//调用append(String)方法 相当于 o.append("hello world");
			o.getClass().getMethod("append",paramTypes).invoke(o,values);
			//这里将输出 hello world
			System.out.println("o.append(\""+values[0]+"\").toString()="+o.toString());
			//调用方法 o.append(int):认识当参数为int,float,double,char,boolean等基础类型时候怎么调用的
			paramTypes = new Class[]{int.class};
			values = new Object[]{new Integer(100)};
			o.getClass().getMethod("append",paramTypes).invoke(o,values);
			//这里将输出 hello world100
			System.out.println("o.append(\""+values[0]+"\").toString()="+o.toString());
			
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}
}




除了例子中给出的一些用法,其实通过java反射还可以进行更多的事情,有兴趣的朋友可以自己再深入研究下。

如果你要更好的理解一些框架(例如ssh等)的结构,那么你更加需要好好的研究下这个反射机制。

附录:你可以下载本篇使用的例子 ReflectTest.zip



-------------------------------------------------------------
分享知识 分享快乐,分享知识,分享快乐,希望文章能给需要的朋友带来小小的帮助。



4
0
分享到:
评论
2 楼 binjx 2010-06-29  
★★★ 本篇为原创,需要引用转载的朋友请注明:《 http://stephen830.iteye.com/blog/256723 》 谢谢支持! ★★★


Reflection 是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。 (这句话是引用台湾作家侯捷对反射机制描述的一个概念)

java的反射机制从java诞生之日起就成为java的一个重要特性。反射机制也是目前众多框架实现的一个基础。

反射,简单的讲就是根据给出的类的名称,我就可以获得这个类所有的信息(包括属性,构造器,方法等),同时还可以对类的方法进行调用。这在需要动态加载类的情况下尤其显得重要。

目前流行的大部分java框架(例如ssh等)的底层有很多都是基于反射机制来实现的。

从下面的实例中可以了解并学会关于java反射的一些基本特点:
(1)如何获得动态加载类的修饰符,包名,类名,使用的接口,继承的父类
(2)动态获取类的所有属性名,修饰符,属性类型
(3)动态获取所有定义的构造器,构造器使用的参数数量和参数类型
(4)动态获取所有方法,方法的返回值类型,方法名,方法参数数量,方法参数类型
(5)动态调用加载类的方法


下面就从一个例子来深入浅出的认识下java的反射机制: 
1 楼 rossbu 2008-10-24  
complete demo!

相关推荐

    Java高级程序设计实战教程第三章-Java反射机制.pptx

    Java高级程序设计 第3章 Java反射机制 3.1 应用场景 3.2 相关知识3.3 实施过程 3.4 拓展知识3.5 拓展训练 3.6 课后小结3.7 课后习题 3.8 上机实训 Java高级程序设计实战教程第三章-Java反射机制全文共15页,当前为第...

    Java反射机制

    java反射机制的实战练习

    尚硅谷_宋红康_第15章节练习_Java反射机制.doc

    ·拒绝晦涩难懂的呆板教学,宋老师语言生动幽默,举例形象生动深入浅出,迅速让你把握问题本质,四两拨千斤 2.课程内容推陈出新: ·基于JDK 11,将Java8、Java9、Java10、Java11新特性一网打尽 ·课程中,Eclipse...

    java_反射实战代码

    与直接在源代码中的交互是一样的,但又提供了额外的在运行时候的灵活性,但反射的一个最大的弊端就是性能比较差,相同的操作,用反射API所需的时间大概比直接使用慢一两个数量级,不过现在的JVM实现中,java反射的...

    java开发实战经典(名师讲坛)-李兴华-扫描版

    这本书从初学者的角度,以丰富的实例、案例,通俗易懂的语言,简单的...需要理解或掌握的多线程、泛型、枚举、Java反射机制、Annotation、Eclipse开发工具;需要了解或掌握的图形界面、Java网络编程、Java新IO等内容。

    Java-Reflection-Tutorial.pdf

    java 反射实战demo,Java的反射(reflection)机制是指在程序的运行...我理解的Java反射的原理就是获取Class对象然后使用java.lang.reflect里提供的方法操作Class对象,Class与java.lang.reflect构成了java的反射技术。

    尚硅谷_宋红康_第15章_Java反射机制.pdf

    ·拒绝晦涩难懂的呆板教学,宋老师语言生动幽默,举例形象生动深入浅出,迅速让你把握问题本质,四两拨千斤 2.课程内容推陈出新: ·基于JDK 11,将Java8、Java9、Java10、Java11新特性一网打尽 ·课程中,Eclipse...

    java反射机制实战示例分享

    主要介绍了java反射机制实战示例,需要的朋友可以参考下

    Java反射实例

    常用的属性,方法和构造函数的获取实例,个人实际学习总结,亲测有效!

    Java反射、泛型和注解实战之Spring核心注入IOC的实现

    综合运用Java反射、泛型和注解实现的类似Spring的核心注入

    在Java中使用反射API的一个实例

    在不知道类名的情况下如何动态的使用其构造方法来创建对象和不知道其方法名的时候如何动态地使用其方法。

    Java_Web开发实战1200例.第2卷

    赋予学 员面向对象思想,充分理解并运用Java面向对象思想来进行程序开发, 实现开发者从过程时编程到面向对象编程的转变,实现Java编程完整化 ,理解多线程、IO、网络编程、反射机制、Java注解等高级功能。...

    Java EE核心框架实战源代码

    赋予学 员面向对象思想,充分理解并运用Java面向对象思想来进行程序开发, 实现开发者从过程时编程到面向对象编程的转变,实现Java编程完整化 ,理解多线程、IO、网络编程、反射机制、Java注解等高级功能。...

    java高级特性整理资料(反射+并发+jvm)

    包含java三大高级特性的文档,《Java Reflection in Action》、《JAVA并发编程实战》、《JVM调优总结》、《深入理解Java虚拟机JVM高级特性与最佳实践》、《concurrent programming in java》,适合想深入java技术的...

    java教程-每日一课,27天java从入门到进阶

    精品java学习教程,原理讲解+源码实战 27天实现java从入门到进阶 第一天:语言环境 第二天:常量变量 第三天:流程控制 第四、五天:方法与数组 第六天:类 第七天:对象的出生 第八天:类与类继承 第九天:具体到...

    疯狂java讲义.第二版.part5.rar

    全书内容覆盖了Java的基本语法结构、Java的面向对象特征、Java集合框架体系、Java泛型、异常处理、Java GUI编程、JDBC数据库编程、Java注释、Java的IO流体系、Java多线程编程、Java网络通讯编程和Java反射机制;...

    疯狂java讲义

    全书内容覆盖了Java的基本语法结构、Java的面向对象特征、Java集合框架体系、Java泛型、异常处理、Java GUI编程、JDBC数据库编程、Java注释、Java的IO流体系、Java多线程编程、Java网络通信编程和Java反射机制;...

    大学本科Java基础课件涵盖项目源代码课件PPT.zip

    Java基础反射pptx Java基础 多线程.pptx Java基础 异常处理pptx Java基础 枚举&注解pptx Java基础泛型docx Java基础_网络编程pptx Java基础面向对象pptx Java基础_高级类特性.pptx Java基础实战Bank项目文档需求源...

Global site tag (gtag.js) - Google Analytics