偶今天真是郁闷呀,在系统中用了一个静态的hashtable缓存工作流定义(因为在运行期,工作流定
义是不可能改变的),但是偶忘了在调用客户端的JAVABEAN时,业务系统给JAVABEAN的参数重新赋了值,
结果..........,偶都不好意思说了,所有的实例都取了第一次的赋值。于是乎,偶赶紧给JAVABEAN对象
实现了Cloneable,然后在给参数重新赋值的地方,用clone的对象,嘿嘿,应该没问题了吧,重新测
试.........,偶呆了,第二次赋值竟然还是取的缓存的值,MY GOD!难道是偶见鬼了?再仔细瞅瞅,哦
,原来是,javabean对象虽然用了clone后的,但是它的成员对象ParameterInfo还保留着原来的引用,即
内存里虽然是有了两个javabean对象,但是这两个对象都用的是对一个ParameterInfo对象的引用,偶赶
紧去查clone...........唉,偶真是汗颜呀,其实就是一个影子clone和深度clone的问题。原来偶用的竟
是影子clone!
以下引自《java中传值和传址及其引伸深度克隆的思考》
“java中的所有对象都是Object类的子类,Object类定义了protected clone()方法,它的作用和c++
以下引自《java中传值和传址及其引伸深度克隆的思考》
“java中的所有对象都是Object类的子类,Object类定义了protected clone()方法,它的作用和c++
中按位复制是一样的,因此同样会带来如果对象中包含另一个对象(注意是对象不是基本数据类型,基本
数据类型直接就会被复制)的指针(java中的句柄),clone并没有将被包含的对象clone,而是复制了被
包含对象的句柄或者说指针。因此并不能认为复制出来的对象就可以随心所欲的修改,因为它和被clone
的对象都包含同一个对象,因此可能会引起潜在的冲突问题。至于深度clone的方法很简单,就是在子类
中覆盖父类Object类中clone方法,保证每一个被包含的对象都被按照位被clone。如果包含的数据全部是
基本类型数据,那么就什么也不用做了。深度clone还有另一种方法就是利用Serializable,但是对象中被
transient关键字修饰的变量是不会被序列化的. 因为clone用到的地方并不多,就不多说了。但是当你遇
到的时候,一定要小心。”
- 作者:
snowfox2008 2004年07月21日, 星期三 18:59