很多时候,我们会有几个比较相像的类(比如继承了同一个父类的两个子类),他们有着很多相同的属性。这时我们也许会有这样的需求,将一个类中已经赋值的属性填充到另一个类的相同属性中。当然,我们可以手动写get/set,但会堆积大量代码,增加代码长度,降低代码可读性。
这时可以用到org.apache.commons.beanutils.BeanUtils包下的copyProperties()方法,该方法定义如下。
public static void copyProperties(Object dest,
Object orig)
throws IllegalAccessException,
InvocationTargetException
Copy property values from the origin bean to the destination bean for all cases where the property names are the same.
Parameters:
dest - Destination bean whose properties are modified
orig - Origin bean whose properties are retrieved
该方法可以将一个类的属性值拷贝到另一个类中相同的属性中。其中第一个参数是目的类,将要赋值的类,第二个参数是源,属性值从该类中取。下面从示例代码来看看其用法。
首先我们创建三个类,BeanA,BeanB,BeanC。
package org.kylin.test;
import java.util.ArrayList;
import java.util.List;
public class BeanA {
private int id;
private String name;
private String age;
private String dataA;
private BeanC beanc;
private List<String> list = new ArrayList<String>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getDataA() {
return dataA;
}
public void setDataA(String dataA) {
this.dataA = dataA;
}
public BeanC getBeanc() {
return beanc;
}
public void setBeanc(BeanC beanc) {
this.beanc = beanc;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
@Override
public String toString() {
return "BeanA [id=" + id + ", name=" + name + ", age=" + age + ", dataA=" + dataA + ", beanc=" + beanc.getData()
+ ", list=" + list + "]";
}
}
package org.kylin.test;
import java.util.ArrayList;
import java.util.List;
public class BeanB {
private int id;
private String name;
private int age;
private String dataB;
private BeanC beanc;
private List<String> list = new ArrayList<String>();
public int getId() {
return id;
}
public void setId(int 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;
}
public String getDataB() {
return dataB;
}
public void setDataB(String dataB) {
this.dataB = dataB;
}
public BeanC getBeanc() {
return beanc;
}
public void setBeanc(BeanC beanc) {
this.beanc = beanc;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
@Override
public String toString() {
return "BeanB [id=" + id + ", name=" + name + ", age=" + age + ", dataB=" + dataB + ", beanc=" + beanc.getData()
+ ", list=" + list + "]";
}
}
package org.kylin.test;
public class BeanC {
private String data;
public BeanC(String data) {
this.data = data;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
下面是Main函数
public static void main(String[] args) throws IllegalAccessException, InvocationTargetException {
BeanA a = new BeanA();
BeanB b = new BeanB();
String str = "list";
BeanC c = new BeanC("data_C");
a.setId(1);
a.setName("a");
a.setAge("20");
a.setDataA("dataA");
a.setBeanc(c);
a.setList(Arrays.asList(str));
System.out.println(a.toString());
BeanUtils.copyProperties(b, a);
System.out.println(b.toString());
}
运行结果如下。
BeanA [id=1, name=a, age=20, dataA=dataA, beanc=data_C, list=[list]]
BeanB [id=1, name=a, age=20, dataB=null, beanc=data_C, list=[list]]
值得注意的是,BeanA中的age是String类型的,而BeanB中是int类型的,这里还是赋值过来了,如果类型反之,也是可以的。但是假如A中的age赋值的字符串不是数字,比如含有字母,则是不行的。另外,自定义类型,List等也是可以拷贝的。如果是两个类各自有的属性,则不会另作处理。
另外,org.springframework.beans.BeanUtils中也有这个方法,但是需要注意的是其源和目的的参数顺序是反的,函数定义如下。
public static void copyProperties(Object source,
Object target)
throws BeansException
Copy the property values of the given source bean into the target bean.
Note: The source and target classes do not have to match or even be derived from each other, as long as the properties match. Any bean properties that the source bean exposes but the target bean does not will silently be ignored.
BeanUtils.copyProperties方法的使用可以减少我们手动拷贝属性的代码量,提高代码可读性,但是其时间开销貌似比手动get/set要高不少,所以还是要恰当地使用该方法。