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