本以为这个方法可以方便的clone对象,但写了下测试用例,发现不是
by the way 我用的是commons-beanutils-1.8.2.jar 和 Junit3.jar ,最开始少jar
要commons-logging.jar,看下官网
The commons-beanutils package requires that the following additional packages be available in the application's class path at runtime: Logging Package (Apache Commons), version 1.0 or later Furthermore, if any of the following commons-beanutils classes are used: org.apache.commons.beanutils.BeanMap org.apache.commons.beanutils.BeanPredicate org.apache.commons.beanutils.BeanPropertyValueChangeClosure org.apache.commons.beanutils.BeanPropertyValueEqualsPredicate org.apache.commons.beanutils.BeanToPropertyValueTransformer then the following packages must also be available in the application's class path at runtime: Collections Package (Apache Commons), version 1.0 or later
Teacher类
package clone; public class Teacher { private String name; public Teacher(String name) { super(); this.name = name; } public Teacher() { } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Class类
package clone; public class Class { private int num; private Teacher sir; public Class(int num, Teacher sir) { super(); this.num = num; this.sir = sir; } public Class() { } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public Teacher getSir() { return sir; } public void setSir(Teacher sir) { this.sir = sir; } }
测试用例
package clone; import junit.framework.TestCase; import org.apache.commons.beanutils.BeanUtils; public class Test extends TestCase { public void testClone() throws Exception { Teacher sir = new Teacher("sir1"); Class c = new Class(1, sir); Class c2 = (Class) BeanUtils.cloneBean(c); System.out.println(c.getSir() == c2.getSir()); assertNotSame(c, c2); assertSame(c.getSir(), c2.getSir()); c.getSir().setName("xx"); assertEquals(c2.getSir().getName(), "xx"); System.out.println("clone is not deep"); } public void testClone2() throws Exception { Teacher sir = new Teacher("sir1"); Class c = new Class(1, sir); Teacher sir2 = (Teacher) BeanUtils.cloneBean(c.getSir()); Class c2 = new Class(); BeanUtils.copyProperties(c2, c); c2.setSir(sir2); assertNotSame(c, c2); assertNotSame(c.getSir(), c2.getSir()); c.getSir().setName("xx"); assertFalse(c2.getSir().getName().equals("xx")); System.out.println("clone is deep"); } }
用例改成了最后能够pass的,
BeanUtils.cloneBean() 在源码上看是调用了 getPropertyUtils().copyProperties(newBean, bean);
最后实际上还是复制的引用 ,所以第一个方法无法实现深clone
但BeanUtils还是可以帮助我们减少工作量的,假如类的属性不是基础类型的话(即自定义类),可以先clone出那个自定义类,在把他付给新的类,覆盖原来类的引用,具体做法见第二个测试方法,
不过假如对象自定义类属性多,级别深的话,这样还是很麻烦
在teacher class类上面都写了一个默认的clone方法后
@Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return super.clone(); }
我又写了个测试方法 和第2个基本一样
public void testClone3() throws Exception { Teacher sir = new Teacher("sir1"); Class c = new Class(1, sir); Teacher sir2 = (Teacher) c.getSir().clone(); Class c2 = (Class) c.clone(); c2.setSir(sir2); assertNotSame(c, c2); assertNotSame(c.getSir(), c2.getSir()); c.getSir().setName("xx"); assertFalse(c2.getSir().getName().equals("xx")); System.out.println("clone is deep"); }
pass
看来BeanUtils.cloneBean()是为那些本身没有实现clone方法的类准备的