反射 (Reflection):反射就是让你可以通过名称来得到对象 ( 类,属性,方法 ) 的技术。例如我们可以通过类名来生成一个类的实例;知道了方法名,就可以调用这个方法;知道了属性名就可以访问这个属性的值。
内省 (Introspector): 当Java运行时可检查自身,Java 程序中询问它的一个对象属于何类,然后检查该类构成。它能找出构成该类的所有属性及方法的名称和数据类型。这种能力被称为内省(introspection).
内省是 Java 语言对 Bean 类属性、事件的一种处理方法(也就是说给定一个javabean对象,我们就可以得到/调用它的所有的get/set方法)。
例如类 A 中有属性 name, 那我们可以通过 getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这就是默认的规则。
Java 中提供了一套 API 用来访问某个属性的 getter/setter 方法,通过这些 API 可以使你不需要了解这个规则,这些 API 存放于包 java.beans 中。
一般的做法是通过类 Introspector 的 getBeanInfo方法 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法。
package com.com.test;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
public class IntrospectorTest {
public static void main(String[] args) throws Exception {
SimpleBean sb = new SimpleBean("royzhou", new String[]{"football", "backetball"});
System.out.println(sb);
/**
* 使用Introspector.getBeanInfo(SimpleBean.class)将Bean的属性放入到BeanInfo中。
* 第二个参数为截止参数,表示截止到此类之前,不包括此类。
* 如果不设置的话,那么将会得到本类以及其所有父类的info。
* BeanInfo中包含了SimpleBean的信息
*/
BeanInfo beanInfo = Introspector.getBeanInfo(sb.getClass());
//将每个属性的信息封装到一个PropertyDescriptor形成一个数组其中包括属性名字,读写方法,属性的类型等等
PropertyDescriptor[] propertys = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertys) {
System.out.println("属性名:" + property.getName());
System.out.println("类型:" + property.getPropertyType());
}
System.out.println();
System.out.println("列出SimpleBean的所有方法");
MethodDescriptor[] methods = beanInfo.getMethodDescriptors();
for (MethodDescriptor method : methods) {
System.out.println(method.getName());
}
System.out.println();
/**
*重新设置属性值
*/
for (PropertyDescriptor property : propertys) {
if (property.getPropertyType().isArray()) { //getPropertyType得到属性类型。
if (property.getPropertyType().isArray()) {
if ("hobby".equals(property.getName())) {
//getComponentType()可以得到数组类型的元素类型
if (property.getPropertyType().getComponentType().equals(String.class)) {
//getWriteMethod()得到此属性的set方法----Method对象,然后用invoke调用这个方法
property.getWriteMethod().invoke(sb, new Object[]{new String[]{"tennis", "fishing"}});
}
}
}
} else if ("name".equals(property.getName())) {
property.getWriteMethod().invoke(sb, new Object[]{"royzhou1985"});
}
}
/**
*获取对象的属性值
*/
System.out.println("获取对象的属性值");
for (PropertyDescriptor property : propertys) {
if (property.getPropertyType().isArray()) { //getPropertyType得到属性类型。
//getReadMethod()得到此属性的get方法----Method对象,然后用invoke调用这个方法String[] result=(String[]) property.getReadMethod().invoke(sb, new Object[]{}); System.out.print(property.getName()+":");//getName得到属性名字for (int j = 0; j < result.length; j++) { System.out.print(result[j] + ",");
} else {
System.out.println(property.getName() + ":" + property.getReadMethod().invoke(sb, new Object[]{}));
}
}
}
}
package com.com.test;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.beans.MethodDescriptor;
/**
* @author Jiangming
*/
public class IntrospectorDemo {
public static void main(String[] args) throws Exception {
SimpleBean sb = new SimpleBean("royzhou", new String[]{"football", "backetball"});
System.out.println(sb);
/**
* 使用Introspector.getBeanInfo(SimpleBean.class)将Bean的属性放入到BeanInfo中。
* 第二个参数为截止参数,表示截止到此类之前,不包括此类。
* 如果不设置的话,那么将会得到本类以及其所有父类的info。
* BeanInfo中包含了SimpleBean的信息
*/
BeanInfo beanInfo = Introspector.getBeanInfo(sb.getClass());
//将每个属性的信息封装到一个PropertyDescriptor形成一个数组其中包括属性名字,读写方法,属性的类型等等
PropertyDescriptor[] propertys = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertys) {
System.out.println("属性名:" + property.getName());
System.out.println("类型:" + property.getPropertyType());
}
System.out.println();
System.out.println("列出SimpleBean的所有方法");
MethodDescriptor[] methods = beanInfo.getMethodDescriptors();
for (MethodDescriptor method : methods) {
System.out.println(method.getName());
}
System.out.println();
/**
*重新设置属性值
*/
for (PropertyDescriptor property : propertys) {
if (property.getPropertyType().isArray()) { //getPropertyType得到属性类型。
if (property.getPropertyType().isArray()) {
if ("hobby".equals(property.getName())) {
//getComponentType()可以得到数组类型的元素类型
if (property.getPropertyType().getComponentType().equals(String.class)) { //getWriteMethod()得到此属性的set方法----Method对象,然后用invoke调用这个方法 property.getWriteMethod().invoke(sb, new Object[]{new String[]{"tennis","fishing"}});
}
}
}
} else if ("name".equals(property.getName())) {
property.getWriteMethod().invoke(sb, new Object[]{"royzhou1985"});
}
}
/**
*获取对象的属性值
*/
System.out.println("获取对象的属性值");
for (PropertyDescriptor property : propertys) {
if (property.getPropertyType().isArray()) { //getPropertyType得到属性类型。
//getReadMethod()得到此属性的get方法----Method对象,然后用invoke调用这个方法String[] result=(String[]) property.getReadMethod().invoke(sb, new Object[]{}); System.out.print(property.getName()+":");//getName得到属性名字for (int j = 0; j < result.length; j++) { System.out.print(result[j] + ",");
} else {
System.out.println(property.getName() + ":" + property.getReadMethod().invoke(sb, new Object[]{}));
}
}
}
}
package com.com.test;
/**
* @author Jiangming
*/
public class SimpleBean {
private String name;
private String[] emails;
public SimpleBean() {
}
public SimpleBean(String name, String[] emails) {
this.name = name;
this.emails = emails;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String[] getEmails() {
return emails;
}
public void setEmails(String[] emails) {
this.emails = emails;
}
}