现在的位置: 首页 > 综合 > 正文

JAVA中反射机制的研究

2013年10月13日 ⁄ 综合 ⁄ 共 6122字 ⁄ 字号 评论关闭


 
  Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对大家以后学习框架技术有很大的帮助。

 

那么什么是Java的反射呢?

     JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
     Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

 

Class类

       要正确使用Java反射机制就得使用java.lang.Class这个类。它是Java反射机制的起源。当一个类被加载以后,Java虚拟机就会自动产生一个Class对象。通过这个Class对象我们就能获得加载到虚拟机当中这个Class对象对应的方法、成员以及构造方法的声明和定义等信息。

 

       利用Java反射机制我们可以很灵活的对已经加载到Java虚拟机当中的类信息进行检测。当然这种检测在对运行的性能上会有些减弱,所以什么时候使用反射,就要靠业务的需求、大小,以及经验的积累来决定。


代码示例:

/*
* 内容 : Java的反射机制的学习
* 备注 :
* 	1、通过Class类的三种实例化对象
* 	2、通过class类中的newInstance()实例化对象
* 	3、获取所有接口
*	  	printAllInterfaces( myclass );
*		4、获得父类
*			printSuperClass( myclass );
*		5、获取所有的构造函数
*			printConstructors( myclass );
*		6、输出类中所有方法,包括父类的方法
*			printAllMethods( myclass );
*		7、输出类中所有属性,不包括父类的属性
*			printDeclaredFields( myclass );
*		8、通过反射调用函数
*			reflectInvoke( myclass );
*
* 作者 : UIT-ESPACE XXX
* 日期 :2012-10-28 
*/

// 编译时则为 javac -d . ReflectionDemo.java, 运行时要输入完整路径: java uit.demo.reflection.ReflectionDemo
package uit.demo.reflection;			

import java.util.*;
import java.lang.reflect.*;

// Person实现了Comparable的接口,可以排序
class Person implements Comparable<Person>{
	private String name;
	private int age;
	
	// 无参构造
	public Person(){
		
	}
	
	// 带参构造
	public Person(String name, int age){
		this.name = name;
		this.age = age;	
	}	
	
	// 设置名字
	public void setName(String name){
		this.name = name;
	
	}
	
	// 设置年龄
	public void setAge(int age){
		this.age = age;
	}
	
	// 获取名字
	public String getName(){
		return this.name;	
	}
	
	// 获取年龄
	public int getAge(){
		return this.age;	
	}
	
	// 转换成字符串
	public String toString(){
		return "姓名: " + this.name + ", 年龄: " + this.age;	
	}
	
	// 覆写equals函数,判断对象是否是同一对象
	public boolean equals(Object obj){
		if ( obj == this ){
			return  true;	
		}	
		
		if ( !(obj instanceof Person)){
			return false;	
		}
		
		Person per = (Person)obj;
		if ( per.name.equals(this.name) && per.age == this.age){
			return true;	
		}else{
			return false;	
		}
	}
	
	// 覆写hashCode(),hashCode表示对象的唯一编码
	public int hashCode(){
		return  this.name.hashCode() * this.age;	
	}
	
	// 排序接口的函数实现,使用此函数实现排序
	public int compareTo(Person per){
		if (this.age > per.age){
			return 1;
		}else if(this.age < per.age) {
			return -1;	
		}else {
			// 调用String中的compareTo()方法
			return this.name.compareTo(per.name) ;	
		}
	}
}

// main
public class ReflectionDemo{
	public static void main(String args[]) throws Exception{
		
		Person per = new Person();
		println("per的类为 : " + per.getClass().getName());
		
		// 三种方法实例化Class对象
		Class<?> c1 = null;
		Class<?> c2 = null;
		Class<?> c3 = null;
		
		// 1、最常用的方式是forName的形式
		c1 = Class.forName("uit.demo.reflection.Person");
		c2 = new Person().getClass();
		c3 = Person.class;
		
		println("per的类为 : " + c1.getName());
		println("per的类为 : " + c2.getName());
		println("per的类为 : " + c3.getName());
		
		// 2、通过反射机制实现对象的实例化,前提是自定义的类必须有无参构造函数
		Person per2 = (Person)c1.newInstance();
		per2.setName("反射");
		println(per2 + ",名字为: " + per2.getName() + "\n");
		
		// 3、通过获取构造方法,然后传参数的形式实例化对象
		Person per3 = null;
		// 获取所有的构造函数
		Constructor<?> con[] = c1.getConstructors();
		for ( Constructor<?> pers : con){
			println( "构造函数 : " + pers.toString() );	
		}
		println("\n");
		
		// 4、通过带参数的构造函数传参来实例化
		per3 = (Person)con[1].newInstance("某某人", 21);
		println( "通过反射机制和带参构造函数实例化: " + per3.toString() + "\n");
		
		
		// 5、获得类的所有结构,包括属性、方法、实现的接口、父类等
		getClassAll();
		
	}
	
	// 通过反射机制取得类的结构,包括属性、方法、接口、父类等
	public static void getClassAll() throws Exception{
		println("*****************************类的结构****************************");
		// 1、实例化Class对象
		Class<?> myclass = Class.forName("uit.demo.reflection.Person");

		// 2、获取所有接口
		printAllInterfaces( myclass );
		// 3、获得父类
		printSuperClass( myclass );
		// 4、获取所有的构造函数
		printConstructors( myclass );
		// 输出类中所有方法,包括父类的方法
		printAllMethods( myclass );
		// 输出类中所有属性,不包括父类的属性
		printDeclaredFields( myclass );
		// 通过反射调用函数
		reflectInvoke( myclass );
		
		println("*************************** FINAL END ******************************\n");
	}
	
	// 输出所有接口
	public static void printAllInterfaces( Class<?> myclass ){
		// 获取所有接口
		Class<?> iterfaceAll[] = myclass.getInterfaces();
		for ( Class<?> temp : iterfaceAll){
			println("实现了接口: " + temp);	
		}
	}
	
	// 输出父类
	public static void printSuperClass( Class<?> myclass ){
		// 获取父类
		Class<?> supercs = myclass.getSuperclass();
		println("父类: " + supercs + "\n");	
		
	}
	
	// 输出所有构造函数
	public static void printConstructors( Class<?> myclass ){
		// 获取所有构造函数
		Constructor<?> cons[] = myclass.getConstructors();
		for ( Constructor<?> pConstructor : cons){

			println( "构造函数 : " );
			// 获得修饰符,比如public 、private等
			int me = pConstructor.getModifiers();
			print(Modifier.toString( me ) + " ");	
			// 获得构造函数的名字
			print( pConstructor.getName() + "(");
			
			// 获取所有参数
			Class<?> params[] = pConstructor.getParameterTypes();
			for (int i=0; i<params.length; i++){
				print( params[i].getName() + " arg" + i);
				// 后面还有参数,则使用逗号分开
				if ( i < params.length - 1 ){
					print( ", " );	
				}
			}
			println( ")" );
			
		}
		println("\n");
		
	}
	
	// 输出所有类中定义的方法
	public static void printAllMethods( Class<?> myclass){
		
			println("***************类的所有方法,包括父类的方法****************");
			// getDeclaredMethods为得到本类中的所有方法,getMethods为获得所有方法,包括父类中的方法
			Method methods[] = myclass.getMethods();
			
			for (int i=0; i<methods.length; i++){
				// 获得返回值类型
				Class<?> returnType = methods[i].getReturnType();
				// 获得参数列表
				Class<?> params[] = methods[i].getParameterTypes();
				// 获得修饰符,public等
				int md = methods[i].getModifiers();
				
				// 1、输出修饰符
				print( Modifier.toString( md ) + " ");
				// 2、输出返回值类型
				print( returnType + " ");
				// 3、输出函数名
				print( methods[i].getName() + "(");
				// 4、挨个输出参数
				for(int j=0; j<params.length; j++){
					print( params[j].getName() + " arg" + j);
					if ( j < params.length -1 ){
						print( "," );
					}
				}
				print( ")" );
				
				// 获取抛出的异常名称
				Class<?> expt[] = methods[i].getExceptionTypes();
				// 如果含有异常参数则输出
				if (expt.length > 0){
					print( " throws " );
					for (int k=0; k<expt.length; k++){
						print( expt[k].getName());
						if ( k < expt.length - 1 ){
							print( "," );	
						}	
					}	
				}// end if
				print(";\n");
			} // end for		
			
			println("***************类的所有方法,包括父类的方法  END ****************\n\n");
	}
	
	// 输出类中的方法
	public static void printDeclaredFields(Class<?> myclass){
		
		println("********************类的属性*******************");
		// 获取类中的属性,不包括父类的属性
		Field decField[] = myclass.getDeclaredFields();	
		for (int i=0; i<decField.length; i++){
			// 获取修饰符
			String md = Modifier.toString( decField[i].getModifiers() );	
			// 属性的类型
			Class<?> type = decField[i].getType();
			print(md + " " + type.getName() + " " + decField[i].getName() + " ;\n");
		}
		println("********************类的属性*******************\n");
	}
	
	// 通过反射调用成员函数
	public static void reflectInvoke(Class<?> myclass) throws Exception{
		
		// 1、获得setName函数, 参数为String 类型的
		Method mt = myclass.getMethod( "setName", String.class);
		// 2、通过myclass.newInstance()构造对象
		Person per = (Person)myclass.newInstance();
		// 3、通过反射调用setName方法, 有参函数
		mt.invoke( per, "名字:反射调用");
		
		// 调用无参函数, 输出返回的信息
		Method mt2 = myclass.getMethod( "getName" );
		// 调用getName函数返回Person对象的名字
		String name = (String)mt2.invoke( per );
		print(  name + "\n");
		
	}
	
	// 输出信息
	public static void print(String msg){
		System.out.print( msg );	
	}
	
	// 输出信息,换行
	public static void println(String msg){
		System.out.println( msg );	
	}
}


抱歉!评论已关闭.