浅拷贝的定义:
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此在浅拷贝中,克隆对象只会赋值原始对象的值类型成员变量(基本数据类型),而引用数据类型也只是赋值了一份原始对象的引用变量的地址。
浅拷贝
实现浅拷贝的方法(implements cloneable):
public class ShallowCopy{
public static void main(String[] args) throws CloneNotSupportedException {
Song song = new Song("1" , "thank you next" , "I might say ....");
Singer singer = new Singer("1" , "Ariana Grande" , song);
System.out.println(singer);
Singer cloneSinger = (Singer) singer.clone();
System.out.println(cloneSinger);
cloneSinger.getSong().setId("2");
cloneSinger.getSong().setName("one last time");
cloneSinger.getSong().setLyrics("I need to be the one");
System.out.println(singer);
System.out.println(cloneSinger);
}
}
public class Song{
private String id;
private String name;
private String lyrics;
public Song() {
}
public Song(String id, String name, String lyrics) {
this.id = id;
this.name = name;
this.lyrics = lyrics;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLyrics() {
return lyrics;
}
public void setLyrics(String lyrics) {
this.lyrics = lyrics;
}
@Override
public String toString() {
return "Song{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", lyrics='" + lyrics + '\'' +
'}';
}
}
public class Singer implements Cloneable{
private String id;
private String name;
private Song song;
public Singer() {
}
public Singer(String id, String name, Song song) {
this.id = id;
this.name = name;
this.song = song;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Song getSong() {
return song;
}
public void setSong(Song song) {
this.song = song;
}
@Override
public Object clone() throws CloneNotSupportedException {
Singer clone = null;
clone = (Singer) super.clone();
return clone;
}
@Override
public String toString() {
return "Singer{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", song=" + song +
'}';
}
}
最终从结果我么可以知道:
Singer{id='1', name='Ariana Grande', song=Song{id='1', name='thank you next', lyrics='I might say ....'}}
Singer{id='1', name='Ariana Grande', song=Song{id='1', name='thank you next', lyrics='I might say ....'}}
Singer{id='1', name='Ariana Grande', song=Song{id='2', name='one last time', lyrics='I need to be the one'}}
Singer{id='1', name='Ariana Grande', song=Song{id='2', name='one last time', lyrics='I need to be the one'}}
我们只对克隆对象cloneSinger里的进行了Song的修改,但原对象的Song对象也随之变化,所以克隆对象cloneSinger与原对象singer中引用对象song是共用的,我们在修改cloneSinger的同时,singer也发生了改变,所以二者对于song对象的引用,指向的是同一个地址,可以得出在浅拷贝中,克隆对象只会赋值原始对象的值类型成员变量(基本数据类型),而引用数据类型也只是赋值了一份原始对象的引用变量的地址。
深拷贝的定义:
深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。此时拷贝出来的新对象,会将原始对象的所有类型进行拷贝。
深拷贝
实现深拷贝的方法(implements cloneable):
public class DeepCopy {
public static void main(String[] args) throws CloneNotSupportedException {
Song song = new Song("1" , "止战之殇" , "光,轻如纸张.....");
Singer singer = new Singer("1" , "周杰伦" , song);
// 对歌手进行deep copy
Singer cloneSinger = (Singer) singer.clone();
cloneSinger.setId("one");
cloneSinger.getSong().setId("2");
cloneSinger.getSong().setName("晴天");
cloneSinger.getSong().setLyrics("刮风这天,我试过握着你手...");
//对cloneSinger与singer进行比较
System.out.println(singer);
System.out.println(cloneSinger);
}
}
public class Singer implements Cloneable{
private String id;
private String name;
private Song song;
public Singer() {
}
public Singer(String id, String name, Song song) {
this.id = id;
this.name = name;
this.song = song;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Song getSong() {
return song;
}
public void setSong(Song song) {
this.song = song;
}
@Override
public Object clone() throws CloneNotSupportedException {
Singer clone = null;
clone = (Singer) super.clone();
clone.setSong((Song) clone.getSong().clone());
return clone;
}
@Override
public String toString() {
return "Singer{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", song=" + song +
'}';
}
}
public class Song implements Cloneable{
private String id;
private String name;
private String lyrics;
public Song() {
}
public Song(String id, String name, String lyrics) {
this.id = id;
this.name = name;
this.lyrics = lyrics;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLyrics() {
return lyrics;
}
public void setLyrics(String lyrics) {
this.lyrics = lyrics;
}
@Override
public Object clone() throws CloneNotSupportedException {
Song clone = null;
clone = (Song) super.clone();
return clone;
}
@Override
public String toString() {
return "Song{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", lyrics='" + lyrics + '\'' +
'}';
}
}
我们可以看到结果
Singer{id='1', name='周杰伦', song=Song{id='1', name='止战之殇', lyrics='光,轻如纸张.....'}}
Singer{id='one', name='周杰伦', song=Song{id='2', name='晴天', lyrics='刮风这天,我试过握着你手...'}}
实现深拷贝的方法(implements Serializable):
public class DeepCopySerializable {
public static void main(String[] args) throws CloneNotSupportedException {
Song song = new Song("1" , "我不配" , "这街道太拥挤,太多人有秘密.....");
Singer singer = new Singer("1" , "周杰伦" , song);
// 对歌手进行deep copy
Singer cloneSinger = (Singer) singer.clone();
cloneSinger.setId("①");
cloneSinger.getSong().setId("2");
cloneSinger.getSong().setName("给我一首歌的时间");
cloneSinger.getSong().setLyrics("能不能给我一首歌的时间...");
//对cloneSinger与singer进行比较
System.out.println(singer);
System.out.println(cloneSinger);
}
}
public class Singer implements Serializable {
private String id;
private String name;
private Song song;
public Singer() {
}
public Singer(String id, String name, Song song) {
this.id = id;
this.name = name;
this.song = song;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Song getSong() {
return song;
}
public void setSong(Song song) {
this.song = song;
}
public Object clone() {
Singer singer = null;
try {
// 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
// 将流序列化成对象
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
singer = (Singer) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return singer;
}
@Override
public String toString() {
return "Singer{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", song=" + song +
'}';
}
}
public class Song implements Serializable {
private String id;
private String name;
private String lyrics;
public Song() {
}
public Song(String id, String name, String lyrics) {
this.id = id;
this.name = name;
this.lyrics = lyrics;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLyrics() {
return lyrics;
}
public void setLyrics(String lyrics) {
this.lyrics = lyrics;
}
@Override
public String toString() {
return "Song{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", lyrics='" + lyrics + '\'' +
'}';
}
}
可以看到结果:
Singer{id='1', name='周杰伦', song=Song{id='1', name='我不配', lyrics='这街道太拥挤,太多人有秘密.....'}}
Singer{id='①', name='周杰伦', song=Song{id='2', name='给我一首歌的时间', lyrics='能不能给我一首歌的时间...'}}
引用数据类型的id(String)和Song对象均进行了拷贝,不像浅拷贝那样,共用一个引用对象,而是有一个新的对象在堆上被创建了。