JAVA的内省(introspector)与反射(reflection)

不少朋友在深刻的接触 JAVA 语言后就会发现这样两个词:反射 (Reflection) 和内省 (Introspector) ,常常搞不清楚这究竟是怎么回事,在什么场合下应用以及如何使用?今天把这两者放在一块儿介绍,由于它们两者是相辅相成的。html

反射java

<?xml:namespace prefix = o /?>
相对而言,反射比内省更容易理解一点。用一句比较白的话来归纳,反射就是让你能够经过名称来获得对象 ( 类,属性,方法 ) 的技术。例如咱们能够经过类名来生成一个类的实例;知道了方法名,就能够调用这个方法;知道了属性名就能够访问这个属性的值。数据库

仍是写两个例子让你们更直观的了解反射的使用方法:框架


// 经过类名来构造一个类的实例
Class cls_str = Class.forName( "java.lang.String" );
// 上面这句很眼熟,由于使用过 JDBC 访问数据库的人都用过 J
Object str = cls_str.newInstance();
// 至关于 String str = new String();
 this


// 经过方法名来调用一个方法
String methodName = "length" ;
Method m = cls_str.getMethod(methodName, null );
System.out.println( "length is " + m.invoke(str, null ));
// 至关于 System.out.println(str.length());
 spa


上面的两个例子是比较经常使用方法。看到上面的例子就有人要发问了:为何要这么麻烦呢?原本一条语句就完成的事情干嘛要整这么复杂?没错,在上面的例子中确实没有必要这么麻烦。不过你想像这样一个应用程序,它支持动态的功能扩展,也就是说程序不从新启动可是能够自动加载新的功能,这个功能使用一个具体类来表示。首先咱们必须为这些功能定义一个接口类,而后咱们要求全部扩展的功能类必须实现我指定的接口,这个规定了应用程序和可扩展功能之间的接口规则,可是怎么动态加载呢?咱们必须让应用程序知道要扩展的功能类的类名,好比是 test.Func1 ,当咱们把这个类名 ( 字符串 ) 告诉应用程序后,它就可使用咱们第一个例子的方法来加载并启用新的功能。这就是类的反射,请问你有别的选择吗?.net


       关于方法的反射建议你们看个人另一篇文章《 利用 Turbine 的事件映射来扩展 Struts 的功能 》,地址是: http://www.javayou.com/article/CSDN/extend_struts.html 。这篇文章详细介绍了若是经过反射来扩展 Struts 框架的功能。设计


内省orm


内省是 Java 语言对 Bean 类属性、事件的一种缺省处理方法。例如类 A 中有属性 name, 那咱们能够经过 getName,setName 来获得其值或者设置新的值。经过 getName/setName 来访问 name 属性,这就是默认的规则。 Java 中提供了一套 API 用来访问某个属性的 getter/setter 方法,经过这些 API 可使你不须要了解这个规则(但你最好仍是要搞清楚),这些 API 存放于包 java.beans 中。xml


通常的作法是经过类 Introspector 来获取某个对象的 BeanInfo 信息,而后经过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),经过这个属性描述器就能够获取某个属性对应的 getter/setter 方法,而后咱们就能够经过反射机制来调用这些方法。下面咱们来看一个例子,这个例子把某个对象的全部属性名称和值都打印出来:


/*
 * Created on 2004-6-29
 */
package demo;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;

/**
  * 内省演示例子
  * @author liudong
  */
public class IntrospectorDemo {
    String name;
    public static void main(String[] args) throws Exception{
        IntrospectorDemo demo = new IntrospectorDemo();
        demo.setName( "Winter Lau" );        
        // 若是不想把父类的属性也列出来的话,
        // 那 getBeanInfo 的第二个参数填写父类的信息
        BeanInfo bi = Introspector.getBeanInfo(demo.getClass(), Object. class );
        PropertyDescriptor[] props = bi.getPropertyDescriptors();
        for ( int i=0;i
            System.out.println(props[i].getName()+ "=" +
                    props[i].getReadMethod().invoke(demo, null ));
        }
    }    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this .name = name;
    }
}
 


Web 开发框架 Struts 中的 FormBean 就是经过内省机制来将表单中的数据映射到类的属性上,所以要求 FormBean 的每一个属性要有 getter/setter 方法。但也并不老是这样,什么意思呢?就是说对一个 Bean 类来说,我能够没有属性,可是只要有 getter/setter 方法中的其中一个,那么 Java 的内省机制就会认为存在一个属性,好比类中有方法 setMobile ,那么就认为存在一个 mobile 的属性,这样能够方便咱们把 Bean 类经过一个接口来定义而不用去关心具体实现,不用去关心 Bean 中数据的存储。好比咱们能够把全部的 getter/setter 方法放到接口里定义,可是真正数据的存取则是在具体类中去实现,这样可提升系统的扩展性。


总结


将 Java 的反射以及内省应用到程序设计中去能够大大的提供程序的智能化和可扩展性。有不少项目都是采起这两种技术来实现其核心功能,例如咱们前面提到的 Struts ,还有用于处理 XML 文件的 Digester 项目,其实应该说几乎全部的项目都或多或少的采用这两种技术。在实际应用过程当中两者要相互结合方能发挥真正的智能化以及高度可扩展性。
 

此文转载自 :想飞的鱼 2007-03-05 17:40

相关文章
相关标签/搜索