深拷贝和浅拷贝的问题无非就是拷贝过程中对象的属性是否指向的是同一个对象引用。
浅拷贝的特点:
一:作为基本数据类型来说,例如int ,double等8类数据类型,拷贝过程中肯定是值的传递,修改另一个对象的数值,不会影响到被拷贝对象的数值。
二:String 类型,String 类型虽然是引用类型,但是String类型的数据是存放在常量池中的,也就是无法修改的!当被拷贝的对象进行修改的时候,是把引用指向了新的地址,而不是在原来的地址上进行修改,所以不影响被拷贝的数据。
三:引用数据类型,例如一个对象,如果是浅拷贝,也就是说被拷贝对象和拷贝对象指向的是同一个引用,那么对其中一个对象进行修改,也会改变另一个对象的值。
1:话不多说,上代码~
public class Clones implements Cloneable {
private String name;
private int size;
private Address address;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public Clones(String name, int size, Address address) {
this.name = name;
this.size = size;
this.address = address;
}
@Override
public String toString() {
return "Clones{" +
"name='" + name + '\'' +
", size=" + size +
", address=" + address +
'}';
}
@Override
protected Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
Address address=new Address("没修改的地址",123456789);
Clones clones=new Clones("没修改",123,address);
Clones copys=(Clones)clones.clone();
System.out.println(copys==clones);
System.out.println(clones.getName()==copys.getName());
System.out.println(clones.getSize()==copys.getSize());
System.out.println(clones.getAddress()==copys.getAddress());
System.out.println(clones.getAddress().getEmail()==copys.getAddress().getEmail());
System.out.println(clones.getAddress().getHost()==copys.getAddress().getHost());
clones.setName("修改了");
clones.setSize(10000);
address.setEmail("修改的邮箱");
address.setHost(7758521);
System.out.println("====================修改后======================");
System.out.println(clones.getName());
System.out.println(clones.getSize());
System.out.println(clones.getAddress().toString());
System.out.println("拷贝的对象~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println(copys.getName());
System.out.println(copys.getSize());
System.out.println(copys.getAddress().toString());
===========================控制台输出结果====================================================
===================================================================================
}
}
class Address{
String email;
int host;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getHost() {
return host;
}
public void setHost(int host) {
this.host = host;
}
public Address(String email, int host) {
this.email = email;
this.host = host;
}
@Override
public String toString() {
return "Address{" +
"email='" + email + '\'' +
", host=" + host +
'}';
}
}
那么问题来了,怎么实现深拷贝呢,其实有两个实现深拷贝的方式,
- 方式一:
需要为对象的每一层的每一个对象都实现Cloneable接口并重写clone方法
2:话不多说,继续上代码~
public class Clones implements Cloneable {
private String name;
private int size;
private Address address;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public Clones(String name, int size, Address address) {
this.name = name;
this.size = size;
this.address = address;
}
@Override
public String toString() {
return "Clones{" +
"name='" + name + '\'' +
", size=" + size +
", address=" + address +
'}';
}
@Override
protected Object clone() {
Object obj=null;
try {
obj= super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
Clones clones=(Clones)obj;
clones.address=(Address)clones.getAddress().clone();
return obj;
}
public static void main(String[] args) {
Address address=new Address("没修改的地址",123456789);
Clones clones=new Clones("没修改",123,address);
Clones copys=(Clones)clones.clone();
System.out.println(copys==clones);
System.out.println(clones.getName()==copys.getName());
System.out.println(clones.getSize()==copys.getSize());
System.out.println(clones.getAddress()==copys.getAddress());
System.out.println(clones.getAddress().getEmail()==copys.getAddress().getEmail());
System.out.println(clones.getAddress().getHost()==copys.getAddress().getHost());
clones.setName("修改了");
clones.setSize(10000);
address.setEmail("修改的邮箱");
address.setHost(7758521);
System.out.println("====================修改后======================");
System.out.println(clones.getName());
System.out.println(clones.getSize());
System.out.println(clones.getAddress().toString());
System.out.println("拷贝的对象~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println(copys.getName());
System.out.println(copys.getSize());
System.out.println(copys.getAddress().toString());
===========================控制台输出结果====================================================
===================================================================================
}
}
class Address implements Cloneable{
String email;
int host;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getHost() {
return host;
}
public void setHost(int host) {
this.host = host;
}
public Address(String email, int host) {
this.email = email;
this.host = host;
}
@Override
public String toString() {
return "Address{" +
"email='" + email + '\'' +
", host=" + host +
'}';
}
@Override
protected Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
将对象序列化为字节序列后,默认会将该对象的整个对象图进行序列化,再通过反序列即可完美地实现深拷贝。
3:话不多说,继续上代码~
public class Clones implements Serializable {
private String name;
private int size;
private Address address;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public Clones(String name, int size, Address address) {
this.name = name;
this.size = size;
this.address = address;
}
@Override
public String toString() {
return "Clones{" +
"name='" + name + '\'' +
", size=" + size +
", address=" + address +
'}';
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
Address address=new Address("没修改的地址",123456789);
Clones clones=new Clones("没修改",123,address);
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(clones);
oos.flush();
ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
Clones copys=(Clones)ois.readObject();
System.out.println(copys==clones);
System.out.println(clones.getName()==copys.getName());
System.out.println(clones.getSize()==copys.getSize());
System.out.println(clones.getAddress()==copys.getAddress());
System.out.println(clones.getAddress().getEmail()==copys.getAddress().getEmail());
System.out.println(clones.getAddress().getHost()==copys.getAddress().getHost());
clones.setName("修改了");
clones.setSize(10000);
address.setEmail("修改的邮箱");
address.setHost(7758521);
System.out.println("====================修改后======================");
System.out.println(clones.getName());
System.out.println(clones.getSize());
System.out.println(clones.getAddress().toString());
System.out.println("深拷贝的对象~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println(copys.getName());
System.out.println(copys.getSize());
System.out.println(copys.getAddress().toString());
===========================控制台输出结果====================================================
===================================================================================
}
}
class Address implements Serializable {
String email;
int host;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getHost() {
return host;
}
public void setHost(int host) {
this.host = host;
}
public Address(String email, int host) {
this.email = email;
this.host = host;
}
@Override
public String toString() {
return "Address{" +
"email='" + email + '\'' +
", host=" + host +
'}';
}
}