标签:
思考问题:如何快速复制出一个属性相同的对象(内存地址不同)?
解答:clone方法,也就是原型模式(逼格很高)。
clone方法有两种方式:
浅克隆与深克隆的区别:
1. 浅克隆用于只包含基本数据类型或String属性的类中;
2. 深克隆用于至少包含一个非基本数据类型(除String类型)属性的类中。比如存在Date类型的属性时就应该考虑深克隆;
3. 实现上的区别:浅克隆只需要简单重写一下Object的clone方法即可(即调用super.clone();),而深克隆除了调用super.clone();之外,还要对非基本数据类型的属性调用clone()函数(才能解除两个对象对同一个属性对象的引用);
下面是只含基本数据类型属性的对象的clone:
但对一个包含非基本数据类型属性的对象进行浅克隆(只是调用一下super.clone();)产生的对象如图(两个对象都引用第三个对象,当一个对象修改birthday时会导致另外一个对象的属性值也跟着改变):
对包含非基本数据类型属性的对象进行深克隆产生的对象如图(一个对象修改birthday不会导致另外一个对象birthday属性改变):
下面是实例代码:
举一个简单版的克隆羊的例子吧!
一个类搞定,不想弄的太复杂!
package com.shusheng.prototype;
/**羊*/
public class Sheep implements Cloneable {
private int num;//小羊的编号
//构造函数
public Sheep(int num){
this.num = num;
}
/**重写object类的clone方法*/
@Override
protected Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
/***测试函数*/
public static void main(String[] args) {
Sheep sheep = new Sheep(1);//new一个小羊
System.out.println(sheep);//查看内存地址
System.out.println(sheep.num);//查看编号
sheep = (Sheep) sheep.clone();//克隆
System.out.println(sheep);//打印克隆出来的小羊的内存地址
System.out.println(sheep.num);//看看克隆出来的小羊的编号
}
}
从上面的地址可以看出克隆出来的对象内存地址是不一样的。
注意点:
1. 需要实现克隆功能的类要实现Cloneable接口(标志这个类的对象是可以被克隆的);
2. 需要重写一下clone方法;(对于浅克隆直接重写就好了)
还是克隆羊的例子:
还是一个类解决吧:
package com.shusheng.prototype;
import java.util.Date;
/**羊*/
public class Sheep1 implements Cloneable {
private int num;//小羊的编号
private Date birthday;//小羊的生日
public Sheep1(int num,Date birthday){//构造函数
this.num = num;
this.birthday = birthday;
}
/**object类的clone方法*/
@Override
protected Object clone() {
Sheep1 cloneSheep = null;//克隆羊
try {
cloneSheep = (Sheep1) super.clone();//对对象进行clone
cloneSheep.birthday = (Date) this.birthday.clone();//对属性进行clone
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return cloneSheep;
}
/***main函数*/
public static void main(String[] args) {
Sheep1 sheep = new Sheep1(1,new Date());//new一个小羊
System.out.println("原来的羊的num:"+sheep.num+",birthday="+sheep.birthday+"\n");
Sheep1 cloneSheep = (Sheep1) sheep.clone();//克隆出一个克隆羊
cloneSheep.birthday.setHours(00);//修改克隆羊的出生时间
System.out.println("克隆羊的num:"+cloneSheep.num+",birthday="+cloneSheep.birthday+"\n");//看看克隆出来的小羊的编号
System.out.println("原来的那头羊的出生日期未变:"+sheep.birthday);
}
}
补充:虽然String对象作为属性时也是非基本数据类型,但是由于String类是不可变类,一个string对象产生后就无法修改对象中字符串的值。所以如果一个对象修改了自身的String类的属性,代表它已经指向另外一个对象去了,而不是修改原来的那个属性对象。
(StringBuffer和StringBuilder类的对象是可变值的,跟String不一样,请区别对待。)
(如果写得好请点个赞,如果写的不好留下宝贵意见可好?)
标签:
原文地址:http://blog.csdn.net/petershusheng/article/details/51339180