1.BeanUtils.copyProperties()介绍
BeanUtils.copyProperties()
是Apache Commons BeanUtils包中提供的一个静态方法,用于快速地从一个Java Bean对象复制属性到另一个Java Bean对象。该方法基于反射机制,通过获取源对象和目标对象的属性名称,然后直接设置目标对象的属性值,从而实现属性的复制。
以下是BeanUtils.copyProperties()
的用法示例:
import org.apache.commons.beanutils.BeanUtils;
public class Main {
public static void main(String[] args) {
Person source = new Person("John", 30);
Person target = new Person();
BeanUtils.copyProperties(source, target);
System.out.println(target.getName()); // 输出: John
System.out.println(target.getAge()); // 输出: 30
}
}
class Person {
private String name;
private int age;
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;
}
}
在这个例子中,我们首先创建了一个Person
对象source
,然后创建了一个空的Person
对象target
。接着,我们调用BeanUtils.copyProperties()
方法,将source
对象的属性复制到target
对象中。
2、使用BeanUtils.copyProperties(source, target)时的注意事项
最近总结了以下几个方面:
我将针对这三点注意事项分别给出例子说明。
-
目标类和源类的属性都要提供get/set方法
如果目标类和源类的属性没有提供get/set方法,那么在使用
BeanUtils.copyProperties()
方法时,就会抛出NoSuchMethodException
异常。这是因为BeanUtils.copyProperties()
方法依赖于get/set方法来获取和设置属性值。例如,考虑以下两个类:
class Source { private String name; private int age; } class Target { private String name; private int age; }
在这两个类中,虽然属性名相同,但是它们都没有提供get/set方法。如果我们尝试使用
BeanUtils.copyProperties()
方法来复制属性值,就会得到如下错误信息:java.lang.NoSuchMethodException: Source.<init>()
这是因为
BeanUtils.copyProperties()
方法试图通过构造函数来创建目标对象,但由于源类没有提供无参构造函数,所以抛出了这个异常。解决这个问题的方法很简单,只需为每个类添加get/set方法即可:
class Source { private String name; private int age; 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 Target { private String name; private int age; 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; } }
现在,我们可以安全地使用
BeanUtils.copyProperties()
方法来复制属性值了。 -
使用这个方法的前提是要确保两个类中的属性名相同,且不会轻易变化
如果目标类和源类的属性名不一致,或者属性名经常发生变化,那么在使用
BeanUtils.copyProperties()
方法时,可能会导致复制过程失败或产生意想不到的结果。例如,考虑以下两个类:
class Source { private String firstName; private String lastName; } class Target { private String fullName; }
在这两个类中,虽然属性名都是字符串类型,但是它们的含义不同。如果我们尝试使用
BeanUtils.copyProperties()
方法来复制属性值,就会得到如下错误信息:java.lang.IllegalArgumentException: Property 'fullName' not found in source object of type 'Source'
这是因为
BeanUtils.copyProperties()
方法无法找到源对象中的fullName
属性,从而抛出了这个异常。解决这个问题的方法也很简单,只需确保源类和目标类的属性名完全匹配即可:
class Source { private String firstName; private String lastName; } class Target { private String firstName; private String lastName; }
现在,我们可以安全地使用
BeanUtils.copyProperties()
方法来复制属性值了。 -
只能针对基本数据类型的属性进行复制,自定义类需要单独处理,不能直接复制
BeanUtils.copyProperties()
方法只能处理基本数据类型的属性,对于自定义类的属性,它并不能直接复制。如果我们尝试复制自定义类的属性,就会得到如下错误信息:java.lang.ClassCastException: java.lang.String cannot be cast to com.example.MyClass
这是因为
BeanUtils.copyProperties()
方法试图将源对象中的属性值转换为目标对象的属性类型,但由于属性类型不匹配,所以抛出了这个异常。例如,考虑以下两个类:
class Source { private MyClass myObject; } class Target { private MyClass myObject; } class MyClass { private String value; }
在这两个类中,虽然属性类型都是
MyClass
,但是它们的内部结构不同。如果我们尝试使用BeanUtils.copyProperties()
方法来复制属性值,就会得到上述错误信息。
3.用法拓展:深浅拷贝
BeanUtils.copyProperties()
这个方法实际上支持两种不同的属性复制策略:浅拷贝和深拷贝。
-
浅拷贝:只复制对象的引用,而不复制对象本身。这意味着如果源对象和目标对象指向同一个内存地址,那么它们实际上是共享同一个对象的副本。在
BeanUtils.copyProperties()
方法中,默认采用的是浅拷贝策略。 -
深拷贝:不仅复制对象的引用,还复制对象本身。这意味着即使源对象和目标对象指向同一个内存地址,它们也是各自独立的对象。要实现深拷贝,我们需要显式地指定
BeanUtils.copyProperties()
方法的第三个参数为true
。
在实际应用中,选择哪种方式取决于具体的需求。例如,如果你希望在复制过程中创建一个新的对象实例,那么就需要进行深拷贝。反之,如果你只需要复制对象的引用,那么浅拷贝就足够了。
举个例子,假设我们有两个类Person
和Employee
,其中Employee
是Person
的一个子类。现在我们想要从一个Person
对象复制到一个Employee
对象中,同时保持Employee
对象的独立性。
class Person {
private String name;
private int age;
// getter and setter methods
}
class Employee extends Person {
private double salary;
// getter and setter methods
}
public class Main {
public static void main(String[] args) {
Person person = new Person();
person.setName("John");
person.setAge(30);
Employee employee = new Employee();
BeanUtils.copyProperties(person, employee); // shallow copy
// 修改person对象的属性
person.setName("Jane");
person.setAge(35);
// 查看employee对象是否受到影响
System.out.println(employee.getName()); // 输出: John
System.out.println(employee.getAge()); // 输出: 30
}
}
在这个例子中,我们首先创建了一个Person
对象并设置其属性。然后,我们创建了一个Employee
对象,并使用BeanUtils.copyProperties()
方法进行浅复制。接着,我们修改了person
对象的属性,但是当我们查看employee
对象的属性时,发现它们并没有被更新。这是因为BeanUtils.copyProperties()
方法默认采用浅拷贝策略,它只复制了对象的引用,而没有复制对象本身。
如果我们想要进行深拷贝,可以使用BeanUtils.copyProperties()
方法的另一个变体BeanUtils.copyProperties(source, target, true)
,其中第三个参数true
表示进行深拷贝。这样,即使我们修改了person
对象的属性,employee
对象也会相应地更新。
4、总结
总的来说,BeanUtils.copyProperties()
方法提供了快速复制Java Bean对象属性的便捷方式,但在使用时需要注意各种注意事项。只有正确理解并遵循这些原则,才能确保程序的正确性和稳定性。
本篇遇到一些注意事项总结如下:
1.目标类和源类的属性都要提供get/set方法,否则无法复制值
2.使用这个方法,前提是要确保两个类中的属性名相同,且不会轻易变化,否则还是建议使用get/set老老实实赋值
3.只能针对基本数据类型的属性进行复制,自定义类需要单独处理,不能直接复制。
日后也会再加以补充。