一、内省与反射
1.Introspector(内省)
内省是基于反射实现的,主要用来操作JavaBean,通过内省可以很方便的动态获取JavaBean的属性、set/get方法
2.reflect(反射)
反射就是运行时获取一个类的所有信息,可以获取.class的任何定义信息构造器、成员变量、成员方法
public class Person {
private String userName;
private Integer userAge;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getUserAge() {
return userAge;
}
public void setUserAge(Integer userAge) {
this.userAge = userAge;
}
@Override
public String toString() {
return "Person{" +
"userName='" + userName + '\'' +
", userAge=" + userAge +
'}';
}
}
二、Introspector
1.PropertyDescriptor类
PropertyDescriptor属性描述器,描述一个属性
- public String getName() 获得属性名
- public synchronized Method getWriteMethod()获得写入属性值的方法
- public synchronized Method getReadMethod()获得读取属性值的方法
@Test
public void testPropertyDescriptor() throws Exception {
Person person = new Person();
PropertyDescriptor propDesc = new PropertyDescriptor("userName", Person.class);
// propName
String propName = propDesc.getName();
System.out.println(propName);
// set
Method setMethod = propDesc.getWriteMethod();
setMethod.invoke(person, "Jack");
System.out.println(person.getUserName());
// get
Method getMethod = propDesc.getReadMethod();
Object obj = getMethod.invoke(person);
System.out.println(obj);
}
结果:
2.Introspector类
通过Introspector类可以获得JavaBean的所有属性
@Test
public void testIntrospector() throws IntrospectionException {
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
PropertyDescriptor[] propDescs = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propDesc : propDescs) {
System.out.println(propDesc.getName());
System.out.println(propDesc.getReadMethod());
System.out.println(propDesc.getWriteMethod());
}
}
结果:
三、BeanUtils
Apache提供BeanUtills工具包操作JavaBean属性
- public static void setProperty(final Object bean, final String name, final Object value) 设置属性值
- public static String getProperty(final Object bean, final String name) 获得属性值
- public static void copyProperty(final Object bean, final String name, final Object value) 将属性值复制到bean
- public static void copyProperties(final Object dest, final Object orig) 将原始bean复制到目标bean(深克隆)
- public static void populate(final Object bean, final Map<String, ? extends Object> properties) map赋值到bean
1.maven依赖
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
2.使用
@Test
public void testBeanUtils() throws Exception {
Person person = new Person();
// setProperty
BeanUtils.setProperty(person, "userName", "Rose");
System.out.println(person.getUserName());
// getProperty
String userName = BeanUtils.getProperty(person, "userName");
System.out.println(userName);
}
@Test
public void testBeanUtilsPopulate() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("userAge", "18");
map.put("no", "no"); // 不存在的属性不会出现异常
Person person = new Person();
BeanUtils.populate(person, map);
System.out.println(person);
}
3.BeanUtils的优势
- BeanUtils相对于Introspector代码少
- Introspector写入属性值是需要知道参数类型,BeanUtils可以自动类型转换
- Introspector对于不存在的属性会出现异常,BeanUtils不会报错
对于userAge赋值,Introspector的Method需要传入int类型,否则会报错
@Test
public void testPropertyDescriptorUserAge() throws Exception {
Person person = new Person();
PropertyDescriptor propDesc = new PropertyDescriptor("userAge", Person.class);
// set
Method setMethod = propDesc.getWriteMethod();
// 会出现异常,参数不匹配,值需要为int类型
setMethod.invoke(person, "18");
System.out.println(person.getUserAge());
}
@Test
public void testBeanUtilsUserAge() throws Exception {
Person person = new Person();
// set
BeanUtils.setProperty(person, "userAge", "18");
System.out.println(person.getUserAge());
}