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 ); } }