- 浏览: 63055 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
风漂雨落:
我怎么觉得你这个例子不像是Builder模式,更像抽象工厂呢, ...
设计模式-创建者模式(Builder) -
linpyi:
tyzqqq 写道jacob依赖于dll,别人要用的话,是不是 ...
jacob实现oracle数据字典 -
tyzqqq:
jacob依赖于dll,别人要用的话,是不是每客户都要下载它的 ...
jacob实现oracle数据字典 -
crabboy:
没运行成功
jacob实现oracle数据字典 -
linpyi:
Wuaner 写道你都说了,“事务尽量在service层操作, ...
JTA (XA)事务和JDBC事务
克隆,大家都听过,JAVA克隆实现的大致意思就是实现类的克隆,为什么JAVA要实现克隆了,那就要说到JAVA里面的指针,引用
我先贴一段测试代码,再慢慢解释
package com.linpyi.clone; public class TestClone { public static void main(String[] args){ TestBean bean1= new TestBean(); //初始化给bean赋值 bean1.setId(1); bean1.setName("name1"); //打印出赋完值的bean System.out.println("bean1.id=="+bean1.getId()+",bean1.name=="+bean1.getName()); System.out.println("******modify******"); //实例化bean2 TestBean bean2 = new TestBean(); //把bean1赋给bean2,实际上这赋的是地址 bean2=bean1; System.out.println("modify before bean1.id=="+bean1.getId()+",bean1.name=="+bean1.getName()); System.out.println("modify before bean2.id=="+bean2.getId()+",bean2.name=="+bean2.getName()); //修改bean1的值 bean1.setId(2); bean1.setName("name2"); //打印出bean1和bean2的值,发现bean2的值随bean1改变而改变,验证上面赋的是地址 System.out.println("modify after bean1.id=="+bean1.getId()+",bean1.name=="+bean1.getName()); System.out.println("modify after bean2.id=="+bean2.getId()+",bean2.name=="+bean2.getName()); System.out.println("\r\n***************clone1****************\r\n"); //实例化bean3 TestBean bean3 = new TestBean(); //使用克隆方法给bean3赋值 bean3=(TestBean)bean1.clone(); //打印未修改bean1前bean1,bean2,bean3的值 System.out.println("clone before bean1.id=="+bean1.getId()+",bean1.name=="+bean1.getName()); System.out.println("clone after bean2.id=="+bean2.getId()+",bean2.name=="+bean2.getName()); System.out.println("clone before bean3.id=="+bean3.getId()+",bean3.name=="+bean3.getName()); //修改bean1的值 bean1.setId(3); bean1.setName("name3"); //打印修改后bean的值,发现只有bean3使用克隆后的bean未改变值 System.out.println("clone after bean1.id=="+bean1.getId()+",bean1.name=="+bean1.getName()); System.out.println("clone after bean2.id=="+bean2.getId()+",bean2.name=="+bean2.getName()); System.out.println("clone after bean3.id=="+bean3.getId()+",bean3.name=="+bean3.getName()); System.out.println("\r\n***************clone2**************\r\n"); //实现影子克隆和深度克隆,以下代码实现了深度克聋 TestBean bean4 = new TestBean(); bean4.setId(4); bean4.setName("name4"); System.out.println("clone bean4.id=="+bean4.getId()+",bean4.name=="+bean4.getName()+",bean4.bean.value=="+bean4.bean.i); TestBean bean5 = new TestBean(); bean5=bean4; System.out.println("clone bean5.id=="+bean5.getId()+",bean5.name=="+bean5.getName()+",bean5.bean.value=="+bean5.bean.i); TestBean bean6 = new TestBean(); bean6=(TestBean)bean4.clone(); System.out.println("clone before bean6.id=="+bean6.getId()+",bean5.name=="+bean6.getName()+",bean6.bean.value=="+bean6.bean.i); bean6.setId(6); bean6.setName("name6"); bean6.bean.setValue(); System.out.println("clone after bean4.id=="+bean4.getId()+",bean4.name=="+bean4.getName()+",bean4.bean.value=="+bean4.bean.i); System.out.println("clone after bean5.id=="+bean5.getId()+",bean5.name=="+bean5.getName()+",bean5.bean.value=="+bean5.bean.i); System.out.println("clone after bean6.id=="+bean6.getId()+",bean5.name=="+bean6.getName()+",bean6.bean.value=="+bean6.bean.i); System.out.println("\r\n***************clone3**************\r\n"); //以下是对克隆String 和 StringBuffer的测试代码 TestBean bean7 = new TestBean(); bean7.setName("nam7"); bean7.pwd="hello world."; bean7.sb = new StringBuffer("hello world."); bean7.sum=10; System.out.println("clone after bean7.pwd=="+bean7.pwd+", bean7.sb=="+bean7.sb+" bean7.sum=="+bean7.sum+", bean7.name=="+bean7.getName()); TestBean bean8 = new TestBean(); bean8=(TestBean)bean7.clone(); System.out.println("clone after bean8.pwd=="+bean8.pwd+", bean8.sb=="+bean8.sb+" bean8.sum=="+bean8.sum+", bean7.name=="+bean8.getName()); //这里实现了对String的克隆,如果改为bean8.pwd=bean8.pwd.substring(0,5)才会有效果,这又是一个赋值,达到假效果;单纯的bean8.pwd.substring(0,5)不会出现任何效果,所以对String和StringBuffer的克隆比较特别 bean8.pwd.substring(0,5); //修改后,bean7的值也改变了 bean8.sb.append("this is world."); //而int型的确没有改变 bean8.sum-=20; //用set方法会就等于重新给他赋值,也可以实现clone的效果 bean8.setName("name8"); System.out.println("clone before bean7.pwd=="+bean7.pwd+", bean7.sb=="+bean7.sb+" bean7.sum=="+bean7.sum+", bean7.name=="+bean7.getName()); System.out.println("clone before bean8.pwd=="+bean8.pwd+", bean8.sb=="+bean8.sb+" bean8.sum=="+bean8.sum+", bean8.name=="+bean8.getName()); } }
javaBean.java
package com.linpyi.clone; /** * 测试JAVABEAN * @author work * */ public class TestBean implements Cloneable{ private int id; private String name; public StringBuffer sb;//公有的变量,测试stringbuffer public String pwd;//公有变量,测试string public int sum;//公有变量,测试int 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 TestBean1 bean = new TestBean1(); public Object clone(){ TestBean o = null; try{ o = (TestBean)super.clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } o.bean = (TestBean1)bean.clone(); return o; } }
TestBean1
package com.linpyi.clone; /** * bean1主要测试深度克隆 * @author work * */ public class TestBean1 implements Cloneable{ public int i=1; public TestBean1(){ } public void setValue(){ i=2; } public Object clone(){ TestBean1 o = null; try{ o = (TestBean1)super.clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } return o; } }
运行结果
bean1.id==1,bean1.name==name1 ******modify****** modify before bean1.id==1,bean1.name==name1 modify before bean2.id==1,bean2.name==name1 modify after bean1.id==2,bean1.name==name2 modify after bean2.id==2,bean2.name==name2 ***************clone1**************** clone before bean1.id==2,bean1.name==name2 clone after bean2.id==2,bean2.name==name2 clone before bean3.id==2,bean3.name==name2 clone after bean1.id==3,bean1.name==name3 clone after bean2.id==3,bean2.name==name3 clone after bean3.id==2,bean3.name==name2 ***************clone2************** clone bean4.id==4,bean4.name==name4,bean4.bean.value==1 clone bean5.id==4,bean5.name==name4,bean5.bean.value==1 clone before bean6.id==4,bean5.name==name4,bean6.bean.value==1 clone after bean4.id==4,bean4.name==name4,bean4.bean.value==1 clone after bean5.id==4,bean5.name==name4,bean5.bean.value==1 clone after bean6.id==6,bean5.name==name6,bean6.bean.value==2 ***************clone3************** clone after bean7.pwd==hello world., bean7.sb==hello world. bean7.sum==10, bean7.name==nam7 clone after bean8.pwd==hello world., bean8.sb==hello world. bean8.sum==10, bean7.name==nam7 clone before bean7.pwd==hello world., bean7.sb==hello world.this is world. bean7.sum==10, bean7.name==nam7 clone before bean8.pwd==hello world., bean8.sb==hello world.this is world. bean8.sum==-10, bean8.name==name8
1.首先我们先测试为什么要使用克隆,作为测试用的克隆,不需要使用TestBean1这个类,TestBean也做相应修改,注释掉
克隆方法里面的 o.bean = (TestBean1)bean.clone();,测试克隆我们只用到
private int id;
private String name;
和他们的set方法
具体代码如下
package com.linpyi.clone; /** * 测试JAVABEAN * @author work * */ public class TestBean implements Cloneable{ private int id; private String name; 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 Object clone(){ TestBean o = null; try{ o = (TestBean)super.clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } // o.bean = (TestBean1)bean.clone(); return o; } }
我们实例化一个TestBean(下面称bean)bean1 然后给他赋初始值,再实例化一个bean2,把bean2=bean1,
打印2个bean的值,发现值是一样的,
接着修改bean1的值,发现2个bean都修改值了,在bean2=bean1的时候实际上指向同一个地址
有很多情况下,我们需要=,但是又需要修改其中的值,因为2个bean我们都需要,当然你可以重新把bean的值打出来再赋给
新的bean,但这样麻烦,所以就产生克隆的概念
说说怎么克隆:
比较经典的方法,其中TestBean可以改为你要克隆的类名
public Object clone(){ TestBean o = null; try{ o = (TestBean)super.clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } o.bean = (TestBean1)bean.clone(); return o; }
在要实现的类上实现implements Cloneable接口
implements Cloneable接口是不包含任何方法的!其实这个接口仅仅是一个标志,而且这个标志也仅仅是针对Object
类中clone()方法的,如果clone类没有实现Cloneable接口,并调用了Object的clone()方法(也就是调用
super.Clone()方法),那么Object的clone()方法就会抛出CloneNotSupportedException异常。
这个接口属于java.lang包,java.lang包已经被缺省的导入类中,所以不需要写成java.lang.Cloneable。另一个值得
请注意的是重载了clone()方法。最后在clone()方法中调用了super.clone(),这也意味着无论clone类的继承结构是什
么样的,super.clone()直接或间接调用了java.lang.Object类的clone()方法。
有了以上的介绍,我们开始测试
首先实现bean3,使用bean3=(TestBean)bean1.clone();方法给bean赋值
其次接着像上面那样修改bean1的值,结果可以发现,随着bean1的修改,bean2的值也改变了,bean3的值确没有改变
说明克隆成功
clone after bean1.id==3,bean1.name==name3 clone after bean2.id==3,bean2.name==name3 clone after bean3.id==2,bean3.name==name2
2.我们来说说影子克隆
实现影子克隆不能使用上面的代码,因为我已经实现了深度克隆,我再介绍下代码
首先我们在上面实现了简单的克隆测试,也了解了JAVA克隆,现在我们的bean中嵌套bean
也就是使用了TestBean1这个类,实现影子克隆的TestBean1的代码如下,和上面有点不一样,
package com.linpyi.clone; /** * bean1主要测试深度克隆 * @author work * */ public class TestBean1{ public int i=1; public TestBean1(){ } public void setValue(){ i=2; } }
TestBean的代码如下
package com.linpyi.clone; /** * 测试JAVABEAN * @author work * */ public class TestBean implements Cloneable{ private int id; private String name; public StringBuffer sb;//公有的变量,测试stringbuffer public String pwd;//公有变量,测试string public int sum;//公有变量,测试int 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 TestBean1 bean = new TestBean1();//其实就是多了一个bean public Object clone(){ TestBean o = null; try{ o = (TestBean)super.clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } return o; } }
然后我们开始测试,使用上面的clone2的代码测试
System.out.println("\r\n***************clone2**************\r\n"); //实现影子克隆和深度克隆 TestBean bean4 = new TestBean(); bean4.setId(4); bean4.setName("name4"); System.out.println("clone bean4.id=="+bean4.getId()+",bean4.name=="+bean4.getName()+",bean4.bean.value=="+bean4.bean.i); TestBean bean5 = new TestBean(); bean5=bean4; System.out.println("clone bean5.id=="+bean5.getId()+",bean5.name=="+bean5.getName()+",bean5.bean.value=="+bean5.bean.i); TestBean bean6 = new TestBean(); bean6=(TestBean)bean4.clone(); System.out.println("clone before bean6.id=="+bean6.getId()+",bean5.name=="+bean6.getName()+",bean6.bean.value=="+bean6.bean.i); bean6.setId(6); bean6.setName("name6"); bean6.bean.setValue();//对TestBean1进行赋值 System.out.println("clone after bean4.id=="+bean4.getId()+",bean4.name=="+bean4.getName()+",bean4.bean.value=="+bean4.bean.i); System.out.println("clone after bean5.id=="+bean5.getId()+",bean5.name=="+bean5.getName()+",bean5.bean.value=="+bean5.bean.i); System.out.println("clone after bean6.id=="+bean6.getId()+",bean5.name=="+bean6.getName()+",bean6.bean.value=="+bean6.bean.i);
其实原理和上面的克垄一样,只是多了一个对TestBean1中i的赋值
运行结果
***************clone2************** clone bean4.id==4,bean4.name==name4,bean4.bean.value==1 clone bean5.id==4,bean5.name==name4,bean5.bean.value==1 clone before bean6.id==4,bean5.name==name4,bean6.bean.value==1 clone after bean4.id==4,bean4.name==name4,bean4.bean.value==2 clone after bean5.id==4,bean5.name==name4,bean5.bean.value==2 clone after bean6.id==6,bean5.name==name6,bean6.bean.value==2
我们实现了一个bean4和bean5,对bean4实行赋值,把bean5=bean4,打印出来,很明显2个值是一样的
接着我们实现bean6,对bean6实行对bean4的克聋bean6=(TestBean)bean4.clone();
打印出bean6的值
clone before bean6.id==4,bean5.name==name4,bean6.bean.value==1
和bean4应该是一样的
接着我们改变bean6的值
bean6.setId(6); bean6.setName("name6"); bean6.bean.setValue();//把i的值赋为2
打印出来
clone after bean4.id==4,bean4.name==name4,bean4.bean.value==2 clone after bean5.id==4,bean5.name==name4,bean5.bean.value==2 clone after bean6.id==6,bean5.name==name6,bean6.bean.value==2
发现bean6的id 和name改变了,而bean6中的TestBean1的value值改变了,连bean4和bean5的value一起改变了,
说明克隆失败,为什么了,因为,这只是实行了影子克隆,对深一步的代码没实现克隆,也就是深度克隆
3.深度克隆,
有了上面影子克隆,现在解决上面没解决的问题,
首先,把TestBean1中也实现克隆方法
package com.linpyi.clone; /** * bean1主要测试深度克隆 * @author work * */ public class TestBean1 implements Cloneable{ public int i=1; public TestBean1(){ } public void setValue(){ i=2; } public Object clone(){ TestBean1 o = null; try{ o = (TestBean1)super.clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } return o; } }
在TestBean中加入o.bean = (TestBean1)bean.clone();
package com.linpyi.clone; /** * 测试JAVABEAN * @author work * */ public class TestBean implements Cloneable{ private int id; private String name; public StringBuffer sb;//公有的变量,测试stringbuffer public String pwd;//公有变量,测试string public int sum;//公有变量,测试int 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 TestBean1 bean = new TestBean1(); public Object clone(){ TestBean o = null; try{ o = (TestBean)super.clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } o.bean = (TestBean1)bean.clone(); return o; } }
原理应该和上面的一样,只是多了一个克隆
运行结果
***************clone2************** clone bean4.id==4,bean4.name==name4,bean4.bean.value==1 clone bean5.id==4,bean5.name==name4,bean5.bean.value==1 clone before bean6.id==4,bean5.name==name4,bean6.bean.value==1 clone after bean4.id==4,bean4.name==name4,bean4.bean.value==1 clone after bean5.id==4,bean5.name==name4,bean5.bean.value==1 clone after bean6.id==6,bean5.name==name6,bean6.bean.value==2
实现了影子克隆和深度克隆,克隆也有例外,那就是String和StringBuffer也就是我们克隆3做的事
3.关于String和StringBuffer
String和StringBuffer是比较特殊的类型
同样的代码
System.out.println("\r\n***************clone3**************\r\n"); //以下是对克隆String 和 StringBuffer的测试代码 TestBean bean7 = new TestBean(); bean7.setName("name7"); bean7.pwd="hello world."; bean7.sb = new StringBuffer("hello world."); bean7.sum=10; System.out.println("clone after bean7.pwd=="+bean7.pwd+", bean7.sb=="+bean7.sb+" bean7.sum=="+bean7.sum+", bean7.name=="+bean7.getName()); TestBean bean8 = new TestBean(); bean8=(TestBean)bean7.clone(); System.out.println("clone after bean8.pwd=="+bean8.pwd+", bean8.sb=="+bean8.sb+" bean8.sum=="+bean8.sum+", bean7.name=="+bean8.getName()); //这里实现了对String的克隆,如果改为bean8.pwd=bean8.pwd.substring(0,5)才会有效果,这又是一个赋值,达到假效果;单纯的bean8.pwd.substring(0,5)不会出现任何效果,所以对String和StringBuffer的克隆比较特别 bean8.pwd.substring(0,5); //修改后,bean7的值也改变了 bean8.sb.append("this is world."); //而int型的确没有改变 bean8.sum-=20; //用set方法会就等于重新给他赋值,也可以实现clone的效果 bean8.setName("name8"); System.out.println("clone before bean7.pwd=="+bean7.pwd+", bean7.sb=="+bean7.sb+" bean7.sum=="+bean7.sum+", bean7.name=="+bean7.getName()); System.out.println("clone before bean8.pwd=="+bean8.pwd+", bean8.sb=="+bean8.sb+" bean8.sum=="+bean8.sum+", bean8.name=="+bean8.getName());
在bean中增加
public StringBuffer sb;//公有的变量,测试stringbuffer
public String pwd;//公有变量,测试string
public int sum;//公有变量,测试int
利用公有的,是为了方便测试,不用set方法
实例话bean7给bean7的setName,pwd,StringBuffer,int赋值
使用克隆方法
最后打印出来会发现只有int和setName的值实现了克隆方法,
直接对String和StringBuffer的操作,没有效果,会改变成原来的bean7
如果是bean8.pwd=bean8.pwd.substring(0,5),重新给他赋值的话就可以实现,当然这样属于假克隆
应该知道的是在Java中所有的基本数据类型都有一个相对应的类,象Integer类对应int类型,Double类对应double类型
等等,这些类也与String类相同,都是不可以改变的类。也就是说,这些的类中的所有方法都是不能改变其自身的值的。这
也让我们在编clone类的时候有了一个更多的选择。同时我们也可以把自己的类编成不可更改的类。当然如果想实现就像上
面那样实现辅值,也许能实现克隆.但是StringBuffer在jdk中的不属于final,所以.....
写晕了,
相关推荐
java克隆技术的入门及深入研究,帮助读者更好的理解java克隆技术,掌握关键知识点。
java的两种深度克隆方法,1cloneTest是用Cloneable接口的clone方法实现(对象必须要实现cloneable接口).2cloneSerialize.java是用对象流写对象到byte数组中,然后从byte数组中取得对象.(对象必须要实现serializble接口)
可以更好的去理解java克隆的运用,尤其在多线程的运用过程中,多个对象进行操作过程中,可以先进行对 对象进行 备份,首先就克隆一份,当多线程对对象操作过程中,与异常情况,可以对对象进行恢复,克隆还其他的用途,学会...
现在Clone已经不是一个新鲜词语了,伴随着“多莉”的产生这个词语确实很“火”过一阵子,在java中也有这么一个概念,它可以让我们很方便的“制造”出一个对象的副本来,下面来具体看看java中的Clone机制是如何工作的...
乒乓这是 Pong 的一个非常简单的 Java 克隆,我将它作为一个项目来应用我在 Java 图形编程中学到的东西。 这是众多尝试中的一个,因为我大部分时间都在不知道自己在做什么(自从我最初创建这个克隆以来已经进行了...
在Java编程语言中,克隆是一种创建对象副本的方法,它允许我们复制一个对象并拥有一个完全独立的新实例,而不是仅仅引用原始对象。克隆技术在处理复杂数据结构、避免对象共享以及实现对象复制等方面有着广泛的应用。...
在Java编程语言中,克隆和序列化是两个重要的概念,它们在数据处理和对象管理中扮演着关键角色。下面将分别对这两个概念进行详细解释,并结合实例和源代码进行阐述。 **一、克隆** 1. **克隆定义**:克隆是指创建...
Java 深克隆与浅克隆 Java 中的克隆机制可以让我们方便地制造出一个对象的副本来,但是在克隆过程中需要注意浅克隆和深克隆的区别。 浅克隆(Shallow Clone)是指对对象的域进行简单的 copy,对象的reference变量...
克隆/重制/补丁。 本软件按“原样”分发,不提供任何类型的明示或暗示的保证或条件。 使用原始 EFS 数据文件并需要安装 EFS 1.4。 应该适用于所有模组。 (可能比本文档更易于导航。) 如果您有一个适用于 EFS 但不...
在Java编程语言中,克隆是一种创建对象副本的方法,它允许我们复制一个对象并得到一个与原对象相同但独立的新对象。克隆分为两种主要类型:深克隆和浅克隆。理解这两种克隆的区别是Java面向对象编程中的重要概念。 ...
在Java编程语言中,"深度克隆"是一个重要的概念,主要涉及到对象复制。深度克隆,也称为完全克隆,是指创建一个与原对象相同的新对象,不仅复制原对象的所有属性,还复制了原对象中引用的对象。这通常用于创建一个...
### Java深度克隆知识点详解 #### 一、深度克隆概念 在Java中,深度克隆是一种用于创建对象副本的方法,它可以确保复制出的新对象与原对象之间没有任何引用关系,也就是说,新对象中的所有成员变量(包括引用类型)...
在Java编程语言中,克隆是创建一个对象副本的过程,这个副本与原对象有相同的属性值,但作为不同的对象存在。克隆分为两种主要类型:浅克隆(Shallow Clone)和深克隆(Deep Clone)。这篇博客文章将探讨这两种克隆...
Java中的对象复制与克隆是程序开发中常见的需求,主要用于创建一个对象的副本,而不会影响原始对象的状态。这里主要讨论两种类型的对象拷贝:浅拷贝和深拷贝。 浅拷贝,也称为表面拷贝,是创建一个新的对象,然后将...
Java中的克隆是一种复制对象的方式,它允许创建一个与原对象具有相同属性的新对象。在Java中,克隆是通过`Object`类的`clone()`方法实现的,但使用克隆时有一些特定的要求和限制。 首先,为了能够克隆一个对象,该...
城堡游戏“ Wesnoth之战”的Java克隆单位可以移动一定数量的步骤。 有不同类型的单位,每个单位都有自己的攻击和防御等级。 玩家只能在视线范围内看到敌方单位。 游戏功能包括:随机生成的游戏场,战争迷雾和战斗...