一、前言
本文内容摘自《深入理解Java核心技术:写给Java工程师的干货笔记(基础篇)》一书,2022年出版,作者 张洪亮(@Hollis),阿里巴巴技术专家,著有《Java工程师成神之路》系列文章,《Java工程师成神之路》电子书已开源,可在阿里云开发者社区免费下载。书籍内容比电子书内容要丰富,内容有修改,有需要的读者可以购买正版书籍。
【如何成神:先搬砖,再砌砖,后造砖!】
本文由 @大白有点菜 原创,请勿盗用,转载请说明出处!如果觉得文章还不错,请点点赞,加关注,谢谢!
《Java工程师成神之路》下载地址为:
https://developer.aliyun.com/ebook/395?spm=a2c6h.20345107.ebook-index.24.4c927863j10ats
二、第3章 Java对象【对象的clone方法】
1、浅拷贝(Shadow Clone)
对基本数据类型进行值传递,对引用数据类型进行引用传递的拷贝。java.lang.Object类中的clone方法,用于复制一个新的对象,在不重写的情况下,就是浅拷贝。
Human类代码:
import java.util.StringJoiner;
/**
* 人类类
* @author 大白有点菜
*/
public class Human implements Cloneable {
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address();
address.setCity("广州");
Human human1 = new Human("大白有点菜", address);
Human human2 = (Human) human1.clone();
human2.getAddress().setCity("深圳");
System.out.println("**********分割线1**********");
System.out.println(human1);
System.out.println("**********分割线2**********");
System.out.println(human2);
}
private String name;
private Address address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Human(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
public String toString() {
return new StringJoiner(", ", Human.class.getSimpleName() + "[", "]")
.add("name='" + name + "'")
.add("address=" + address)
.toString();
}
static class Address {
private String city;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return new StringJoiner(", ", Address.class.getSimpleName() + "[", "]")
.add("city='" + city + "'")
.toString();
}
}
}
运行结果:
**********分割线1**********
Human[name='大白有点菜', address=Address[province='深圳']]
**********分割线2**********
Human[name='大白有点菜', address=Address[province='深圳']]
定义了一个Human类并实现Cloneable接口,在main函数里面创建Human类的对象human1和human2,使用clone方法复制human1的新对象并把它赋值给human2,只修改human2的address属性的city的值。最后打印结果,发现human1和human2的值都发生了改变。
2、深拷贝(Deep Clone)
对基本数据进行值传递,为数据类型创建一个新的对象,并复制其内容,此为深拷贝。
Human类代码:
import java.util.StringJoiner;
/**
* 人类类
* @author 大白有点菜
*/
public class Human implements Cloneable {
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address();
address.setCity("广州");
Human human1 = new Human("大白有点菜", address);
Human human2 = (Human) human1.clone();
human2.getAddress().setCity("深圳");
System.out.println("**********分割线1**********");
System.out.println(human1);
System.out.println("**********分割线2**********");
System.out.println(human2);
}
private String name;
private Address address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Human(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
public String toString() {
return new StringJoiner(", ", Human.class.getSimpleName() + "[", "]")
.add("name='" + name + "'")
.add("address=" + address)
.toString();
}
@Override
protected Object clone() throws CloneNotSupportedException {
Human human = (Human) super.clone();
human.setAddress((Address) address.clone());
return human;
}
/**
* 深拷贝的Address类
*/
static class Address implements Cloneable {
private String city;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return new StringJoiner(", ", Address.class.getSimpleName() + "[", "]")
.add("city='" + city + "'")
.toString();
}
}
}
运行结果:
**********分割线1**********
Human[name='大白有点菜', address=Address[city='广州']]
**********分割线2**********
Human[name='大白有点菜', address=Address[city='深圳']]
可以发现,对“clone”出来的新对象的修改并没有影响到原有的对象。