java 中的克隆

来源:互联网 发布:手机医用软件 编辑:程序博客网 时间:2024/05/22 13:21
大家好:今天是我第一次发博客,主要介绍一下java中克隆的有关知识,这和C++中的不一样。

首先看一段程序,以及运行结果。

import java.awt.Color;public class Cfc1{public static void main(String args[]){Cat cat1=new Cat("Java",12,21,Color.black);Cat cat2=new Cat("C++",12,21,Color.white);Cat cat3=new Cat("C#",12,21,Color.black);System.out.println("Before");System.out.println("猫咪1号:"+cat1);System.out.println("猫咪2号:"+cat2);System.out.println("猫咪3号:"+cat3);cat2=cat1;System.out.println("Now");cat2.setInfo();System.out.println("猫咪1号:"+cat1);System.out.println("猫咪2号:"+cat2);System.out.println("猫咪3号:"+cat3);}}class Cat{private String name;private int age;private double weight;private Color color;public Cat(String name,int age,double weight,Color color){this.name=name;this.age=age;this.weight=weight;this.color=color;}public void setInfo(){this.name="VB";this.age=13;this.weight=23;this.color=Color.BLUE;}public boolean equals(Cat cat){if(this==cat){return true;}else{return false;}}public String toString(){StringBuffer sb=new StringBuffer();sb.append("name="+name+"\n");sb.append("age="+age+"\n");sb.append("weight="+weight+"\n");sb.append("Color="+color+"\n");return sb.toString();}}


 

结果如下:

Before
猫咪1号:name=Java
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]

猫咪2号:name=C++
age=12
weight=21.0
Color=java.awt.Color[r=255,g=255,b=255]

猫咪3号:name=C#
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]

Now
猫咪1号:name=VB
age=13
weight=23.0
Color=java.awt.Color[r=0,g=0,b=255]

猫咪2号:name=VB
age=13
weight=23.0
Color=java.awt.Color[r=0,g=0,b=255]

猫咪3号:name=C#
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]

 代码中的cat2.setInfo();明明是修改cat2的,为什么修改cat2之后cat1也改了?

那是因为这里的cat1 ,cat2,cat3,相当于C++中的指针(java 中“没有“指针,只不过是把指针操作封装了,其实是有的这里的cat1 ,cat2,cat3,就相当于地址)

那要克隆的话怎么办呢?

请再看如下代码:

import java.awt.Color;public class Cfc2{public static void main(String args[]){Cat cat1=new Cat("Java",12,21,Color.black);Cat cat2=new Cat("C++",12,21,Color.white);Cat cat3=new Cat("C#",12,21,Color.black);System.out.println("Before");System.out.println("猫咪1号:"+cat1);System.out.println("猫咪2号:"+cat2);System.out.println("猫咪3号:"+cat3);cat2=cat1.clone();System.out.println("Now");cat2.setInfo();System.out.println("猫咪1号:"+cat1);System.out.println("猫咪2号:"+cat2);System.out.println("猫咪3号:"+cat3);}}class Cat implements Cloneable{private String name;private int age;private double weight;private Color color;public Cat(String name,int age,double weight,Color color){this.name=name;this.age=age;this.weight=weight;this.color=color;}public void setInfo(){this.name="VB";this.age=13;this.weight=23;this.color=Color.BLUE;}public boolean equals(Cat cat){if(this==cat){return true;}else{return false;}}public String toString(){StringBuffer sb=new StringBuffer();sb.append("name="+name+"\n");sb.append("age="+age+"\n");sb.append("weight="+weight+"\n");sb.append("Color="+color+"\n");return sb.toString();}public Cat clone(){Cat cat=null;try{cat=(Cat)super.clone();}catch(CloneNotSupportedException e){e.printStackTrace();}return cat;}}

运行结果如下:

Before
猫咪1号:name=Java
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]

猫咪2号:name=C++
age=12
weight=21.0
Color=java.awt.Color[r=255,g=255,b=255]

猫咪3号:name=C#
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]

Now
猫咪1号:name=Java
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]

猫咪2号:name=VB
age=13
weight=23.0
Color=java.awt.Color[r=0,g=0,b=255]

猫咪3号:name=C#
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]

 看!!!  这次cat1没有被修改吧,原因就在于cat2=cat1.clone();  以及class Cat implements Cloneable   cat2相当于拥有了另一块同cat1内容一样的空间 而之前

的那个例子 cat1,cat2是共同指向一个空间,所以cat2.setInfo();之后,cat1也被改了。

可是,再看看下面的程序以及运行结果,你会发现又有问题了。

 

import java.awt.Color;public class Cfc3{public static void main(String args[]){Cat cat1=new Cat("Java",12,21,Color.black,new LikeFood("fish","meet"));Cat cat2=new Cat("C++",12,21,Color.white,new LikeFood("firut","vegtable"));Cat cat3=new Cat("C#",12,21,Color.black,new LikeFood("banana","apple"));System.out.println("Before");System.out.println("猫咪1号:"+cat1);System.out.println("猫咪2号:"+cat2);System.out.println("猫咪3号:"+cat3);cat2=cat1.clone();System.out.println("Now");cat2.setInfo();System.out.println("猫咪1号:"+cat1);System.out.println("猫咪2号:"+cat2);System.out.println("猫咪3号:"+cat3);}}class Cat implements Cloneable{private String name;private int age;private double weight;private Color color;private LikeFood lf;public Cat(String name,int age,double weight,Color color,LikeFood lf){this.name=name;this.age=age;this.weight=weight;this.color=color;this.lf=lf;}public void setInfo(){this.name="VB";this.age=13;this.weight=23;this.color=Color.BLUE;this.lf.setInfo();}public String toString(){StringBuffer sb=new StringBuffer();sb.append("name="+name+"\n");sb.append("age="+age+"\n");sb.append("weight="+weight+"\n");sb.append("Color="+color+"\n");sb.append("LikeFood::"+lf+"\n");return sb.toString();}public Cat clone(){Cat cat=null;try{cat=(Cat)super.clone();}catch(CloneNotSupportedException e){e.printStackTrace();}return cat;}}class LikeFood{private String firstfood;private String secondfood;public LikeFood(String firstfood,String secondfood){this.firstfood=firstfood;this.secondfood=secondfood;}public String toString(){StringBuffer sb=new StringBuffer();sb.append("firstfood="+firstfood+" secondfood="+secondfood);return sb.toString();}public void setInfo(){this.firstfood="sheet";this.secondfood="urine";}}


运行结果如下:

Before
猫咪1号:name=Java
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]
LikeFood::firstfood=fish secondfood=meet

猫咪2号:name=C++
age=12
weight=21.0
Color=java.awt.Color[r=255,g=255,b=255]
LikeFood::firstfood=firut secondfood=vegtable

猫咪3号:name=C#
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]
LikeFood::firstfood=banana secondfood=apple

Now
猫咪1号:name=Java
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]
LikeFood::firstfood=sheet secondfood=urine

猫咪2号:name=VB
age=13
weight=23.0
Color=java.awt.Color[r=0,g=0,b=255]
LikeFood::firstfood=sheet secondfood=urine

猫咪3号:name=C#
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]
LikeFood::firstfood=banana secondfood=apple

 

这次有cat2=cat1.clone(); 怎么cat1有一部分被改变了 ,另一部分没有被改变???

我们还可以发现被改变的不是基本数据类型,而没改的是基本数据类型。

这说明当执行cat2=cat1.clone();之后,对于基本数据类型,是真正意义上的克隆,而对于类变量,不是真正的克隆

还是cat1,cat2共同指向cat1的private LikeFood lf;  所以cat2.setInfo();之后,对于类数据类型的那一部分,cat1`  与cat2都改了。

以下是最终的正确完整的程序:

import java.awt.Color;public class Cfc4{public static void main(String args[]){Cat cat1=new Cat("Java",12,21,Color.black,new LikeFood("fish","meet"));Cat cat2=new Cat("C++",12,21,Color.white,new LikeFood("firut","vegtable"));Cat cat3=new Cat("C#",12,21,Color.black,new LikeFood("banana","apple"));System.out.println("Before");System.out.println("猫咪1号:"+cat1);System.out.println("猫咪2号:"+cat2);System.out.println("猫咪3号:"+cat3);cat2=cat1.clone();cat2.lf=cat2.lf.clone();System.out.println("Now");cat2.setInfo();System.out.println("猫咪1号:"+cat1);System.out.println("猫咪2号:"+cat2);System.out.println("猫咪3号:"+cat3);}}class Cat implements Cloneable{private String name;private int age;private double weight;private Color color;public LikeFood lf;public Cat(String name,int age,double weight,Color color,LikeFood lf){this.name=name;this.age=age;this.weight=weight;this.color=color;this.lf=lf;}public void setInfo(){this.name="VB";this.age=13;this.weight=23;this.color=Color.BLUE;this.lf.setInfo();}public String toString(){StringBuffer sb=new StringBuffer();sb.append("name="+name+"\n");sb.append("age="+age+"\n");sb.append("weight="+weight+"\n");sb.append("Color="+color+"\n");sb.append("LikeFood::"+lf+"\n");return sb.toString();}public Cat clone(){Cat cat=null;try{cat=(Cat)super.clone();}catch(CloneNotSupportedException e){e.printStackTrace();}return cat;}}class LikeFood implements Cloneable{private String firstfood;private String secondfood;public LikeFood(String firstfood,String secondfood){this.firstfood=firstfood;this.secondfood=secondfood;}public String toString(){StringBuffer sb=new StringBuffer();sb.append("firstfood="+firstfood+" secondfood="+secondfood);return sb.toString();}public void setInfo(){this.firstfood="sheet";this.secondfood="urine";}public LikeFood clone(){LikeFood lf=null;try{lf=(LikeFood)super.clone();}catch(CloneNotSupportedException e){e.printStackTrace();}return lf;}}

结果如下:

Before
猫咪1号:name=Java
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]
LikeFood::firstfood=fish secondfood=meet

猫咪2号:name=C++
age=12
weight=21.0
Color=java.awt.Color[r=255,g=255,b=255]
LikeFood::firstfood=firut secondfood=vegtable

猫咪3号:name=C#
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]
LikeFood::firstfood=banana secondfood=apple

Now
猫咪1号:name=Java
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]
LikeFood::firstfood=fish secondfood=meet

猫咪2号:name=VB
age=13
weight=23.0
Color=java.awt.Color[r=0,g=0,b=255]
LikeFood::firstfood=sheet secondfood=urine

猫咪3号:name=C#
age=12
weight=21.0
Color=java.awt.Color[r=0,g=0,b=0]
LikeFood::firstfood=banana secondfood=apple

 看!!!!这下子好了吧!!!

 

总结::Cfc1中克隆出现了问题,Cfc2解决了(这是Cfc1,Cfc2里面的成员变量里没有类这样的数据类型)

                Cfc3中又出现了问题原因在于成员变量中加入了类这样的数据类型,对于这样的类,也要implements Cloneable

                才行,所以Cfc4出现了,解决了比较完整的问题              

                 当然对于对象的克隆也可以通过序列化的方法解决,过程会简单一点,但是序列化的方法效率没有本文的方法好




 

原创粉丝点击