首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

java 反照机制实例解释

2012-12-25 
java 反射机制实例解释在 Java 运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一

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


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

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

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
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类是一个JavaBeanprivate 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
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 基本类型的包装类:
Object result=addMethod.invoke(invokeTester,
new Object[]{new Integer(100),new Integer(200)});
System.out.println((Integer)result); //result 为Integer类型

未完待续。。。。。。

热点排行