java反射机制实例解析

在 Java 运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意
一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息,以及动态
调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。Java 反射机制主要提供
了以下功能:
在运行时判断任意一个对象所属的类;
在运行时构造任意一个类的对象;
在运行时判断任意一个类所具有的成员变量和方法;
在运行时调用任意一个对象的方法;
生成动态代理。


在 JDK 中,主要由以下类来实现Java 反射机制,这些类都位于java.lang.reflect
包中。
  Class类:代表一个类。
  Field类:代表类的成员变量(成员变量也称为类的属性)。
  Method类:代表类的方法。
  Constructor 类:代表类的构造方法。
  Array类:提供了动态创建数组,以及访问数组元素的静态方法。

如例程1所示DumpMethods 类演示了Reflection API的基本作用,它读取命令
行参数指定的类名,然后打印这个类所具有的方法信息:
例程1:DumpMethods.java

Java代码 复制代码  收藏代码
  1. import java.lang.reflect.*;   
  2.   
  3. public class DumpMethods {   
  4.     public static void main(String args[]) throws Exception {   
  5.         // 加载并初始化命令行参数指定的类   
  6.         Class classType = Class.forName(args[0]);   
  7.         // 获得类的所有方法   
  8.         Method methods[] = classType.getDeclaredMethods();   
  9.         for (int i = 0; i < methods.length; i++)   
  10.             System.out.println(methods[i].toString());   
  11.     }   
  12. }  
import java.lang.reflect.*;

public class DumpMethods {
	public static void main(String args[]) throws Exception {
		// 加载并初始化命令行参数指定的类
		Class classType = Class.forName(args[0]);
		// 获得类的所有方法
		Method methods[] = classType.getDeclaredMethods();
		for (int i = 0; i < methods.length; i++)
			System.out.println(methods[i].toString());
	}
}


运行命令“java DumpMethods java.util.Stack”,就会显示java.util.Stack类所具有的方法,程序的打印结果如下:
public synchronized java.lang.Object java.util.Stack.pop()
public java.lang.Object java.util.Stack.push(java.lang.Object)
public boolean java.util.Stack.empty()
public synchronized java.lang.Object java.util.Stack.peek()
public synchronized int java.util.Stack.search(java.lang.Object)

如例程2 所示ReflectTester 类进一步演示了Reflection API 的基本使用方法。
ReflectTester 类有一个copy(Object object)方法,这个方法能够创建一个和参数object同样类型的对象,然后把object对象中的所有属性复制到新建的对象中,并将它返回。这个例子只能复制简单的JavaBean,假定JavaBean的每个属性都有public类型的
getXXX()和setXXX()方法。
例程2 ReflectTester.java

Java代码 复制代码  收藏代码
  1. import java.lang.reflect.*;   
  2.   
  3. public class ReflectTester {   
  4.     public Object copy(Object object) throws Exception {   
  5.         // 获得对象的类型   
  6.         Class classType = object.getClass();   
  7.         System.out.println("Class:" + classType.getName());   
  8.         // 通过默认构造方法创建一个新的对象   
  9.         Object objectCopy = classType.getConstructor(new Class[] {})   
  10.                 .newInstance(new Object[] {});   
  11.         // 获得对象的所有属性   
  12.         Field fields[] = classType.getDeclaredFields();   
  13.         for (int i = 0; i < fields.length; i++) {   
  14.             Field field = fields[i];   
  15.             String fieldName = field.getName();   
  16.             String firstLetter = fieldName.substring(01).toUpperCase();   
  17.             // 获得和属性对应的getXXX()方法的名字   
  18.             String getMethodName = "get" + firstLetter + fieldName.substring(1);   
  19.             // 获得和属性对应的setXXX()方法的名字   
  20.             String setMethodName = "set" + firstLetter + fieldName.substring(1);   
  21.             // 获得和属性对应的getXXX()方法   
  22.             Method getMethod = classType.getMethod(getMethodName,   
  23.                     new Class[] {});   
  24.             // 获得和属性对应的setXXX()方法   
  25.             Method setMethod = classType.getMethod(setMethodName,   
  26.                     new Class[] { field.getType() });   
  27.             // 调用原对象的getXXX()方法   
  28.             Object value = getMethod.invoke(object, new Object[] {});   
  29.             System.out.println(fieldName + ":" + value);   
  30.             // 调用复制对象的setXXX()方法   
  31.             setMethod.invoke(objectCopy, new Object[] { value });   
  32.         }   
  33.         return objectCopy;   
  34.     }   
  35.   
  36.     public static void main(String[] args) throws Exception {   
  37.         Customer customer = new Customer("Tom"21);   
  38.         customer.setId(new Long(1));   
  39.         Customer customerCopy = (Customer) new ReflectTester().copy(customer);   
  40.         System.out.println("Copy information:" + customerCopy.getName() + " "  
  41.                 + customerCopy.getAge());   
  42.     }   
  43. }   
  44.   
  45. class Customer { // Customer类是一个JavaBean   
  46.     private Long id;   
  47.     private String name;   
  48.     private int age;   
  49.   
  50.     public Customer() {   
  51.     }   
  52.   
  53.     public Customer(String name, int age) {   
  54.         this.name = name;   
  55.         this.age = age;   
  56.     }   
  57.   
  58.     public Long getId() {   
  59.         return id;   
  60.     }   
  61.   
  62.     public void setId(Long id) {   
  63.         this.id = id;   
  64.     }   
  65.   
  66.     public String getName() {   
  67.         return name;   
  68.     }   
  69.   
  70.     public void setName(String name) {   
  71.         this.name = name;   
  72.     }   
  73.   
  74.     public int getAge() {   
  75.         return age;   
  76.     }   
  77.   
  78.     public void setAge(int age) {   
  79.         this.age = age;   
  80.     }   
  81. }  
import java.lang.reflect.*;

public class ReflectTester {
	public Object copy(Object object) throws Exception {
		// 获得对象的类型
		Class classType = object.getClass();
		System.out.println("Class:" + classType.getName());
		// 通过默认构造方法创建一个新的对象
		Object objectCopy = classType.getConstructor(new Class[] {})
				.newInstance(new Object[] {});
		// 获得对象的所有属性
		Field fields[] = classType.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			String fieldName = field.getName();
			String firstLetter = fieldName.substring(0, 1).toUpperCase();
			// 获得和属性对应的getXXX()方法的名字
			String getMethodName = "get" + firstLetter + fieldName.substring(1);
			// 获得和属性对应的setXXX()方法的名字
			String setMethodName = "set" + firstLetter + fieldName.substring(1);
			// 获得和属性对应的getXXX()方法
			Method getMethod = classType.getMethod(getMethodName,
					new Class[] {});
			// 获得和属性对应的setXXX()方法
			Method setMethod = classType.getMethod(setMethodName,
					new Class[] { field.getType() });
			// 调用原对象的getXXX()方法
			Object value = getMethod.invoke(object, new Object[] {});
			System.out.println(fieldName + ":" + value);
			// 调用复制对象的setXXX()方法
			setMethod.invoke(objectCopy, new Object[] { value });
		}
		return objectCopy;
	}

	public static void main(String[] args) throws Exception {
		Customer customer = new Customer("Tom", 21);
		customer.setId(new Long(1));
		Customer customerCopy = (Customer) new ReflectTester().copy(customer);
		System.out.println("Copy information:" + customerCopy.getName() + " "
				+ customerCopy.getAge());
	}
}

class Customer { // Customer类是一个JavaBean
	private Long id;
	private String name;
	private int age;

	public Customer() {
	}

	public Customer(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}


执行结果:Class:Customer
id:1
name:Tom
age:21
Copy information:Tom 21
Class类是Reflection API中的核心类,它有以下方法。
  getName():获得类的完整名字。
  getFields():获得类的public类型的属性。
  getDeclaredFields():获得类的所有属性。
  getMethods():获得类的public类型的方法。
  getDeclaredMethods():获得类的所有方法。
getMethod(String name, Class[] parameterTypes):获得类的特定方法,name 参
数指定方法的名字,parameterTypes参数指定方法的参数类型。
  getConstrutors():获得类的public类型的构造方法。
  getConstrutor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes参数指定构造方法的参数类型。

如例程3 所示的InvokeTester 类的main()方法中,运用反射机制调用一个
InvokeTester 对象的add()和echo()方法。
例程3 InvokeTester.java

Java代码 复制代码  收藏代码
  1. import java.lang.reflect.*;   
  2.   
  3. public class InvokeTester {   
  4.     public int add(int param1, int param2) {   
  5.         return param1 + param2;   
  6.     }   
  7.   
  8.     public String echo(String msg) {   
  9.         return "echo:" + msg;   
  10.     }   
  11.   
  12.     public static void main(String[] args) throws Exception {   
  13.         Class classType = InvokeTester.class;   
  14.         Object invokeTester = classType.newInstance();   
  15.         // 调用InvokeTester对象的add()方法   
  16.         Method addMethod = classType.getMethod("add"new Class[] { int.class,   
  17.                 int.class });   
  18.         Object result = addMethod.invoke(invokeTester, new Object[] {   
  19.                 new Integer(100), new Integer(200) });   
  20.         System.out.println((Integer) result);   
  21.         // 调用InvokeTester对象的echo()方法   
  22.         Method echoMethod = classType.getMethod("echo",   
  23.                 new Class[] { String.class });   
  24.         result = echoMethod.invoke(invokeTester, new Object[] { "Hello" });   
  25.         System.out.println((String) result);   
  26.     }   
  27. }  
import java.lang.reflect.*;

public class InvokeTester {
	public int add(int param1, int param2) {
		return param1 + param2;
	}

	public String echo(String msg) {
		return "echo:" + msg;
	}

	public static void main(String[] args) throws Exception {
		Class classType = InvokeTester.class;
		Object invokeTester = classType.newInstance();
		// 调用InvokeTester对象的add()方法
		Method addMethod = classType.getMethod("add", new Class[] { int.class,
				int.class });
		Object result = addMethod.invoke(invokeTester, new Object[] {
				new Integer(100), new Integer(200) });
		System.out.println((Integer) result);
		// 调用InvokeTester对象的echo()方法
		Method echoMethod = classType.getMethod("echo",
				new Class[] { String.class });
		result = echoMethod.invoke(invokeTester, new Object[] { "Hello" });
		System.out.println((String) result);
	}
}


执行结果:300
echo:Hello
add()方法的两个参数为int 类型,获得表示add()方法的Method对象的代码如下:
Method addMethod=classType.getMethod("add",new Class[]{int.class,int.class});
Method类的invoke(Object obj,Object args[])方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。invoke()方法的返回值总是对象,
如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相
应的包装类型的对象,再将其返回。
在本例中,尽管InvokeTester 类的add()方法的两个参数及返回值都是int 类型,调
用addMethod对象的invoke()方法时,只能传递Integer 类型的参数,并且invoke()方法的返回类型也是Integer 类型,Integer 类是int 基本类型的包装类:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值