一、什么是拷贝?
先看下接口说明
/**
* Creates and returns a copy of this object. The precise meaning
* of "copy" may depend on the class of the object. The general
* intent is that, for any object {@code x}, the expression:
* @see java.lang.Cloneable
*/
@IntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
第一句话“Creates and returns a copy of this object.”就说明了,拷贝即创建一个该对象的副本。
二、浅拷贝和深拷贝
还是看接口说明
/** By convention, the object returned by this method should be independent
* of this object (which is being cloned). To achieve this independence,
* it may be necessary to modify one or more fields of the object returned
* by {@code super.clone} before returning it. Typically, this means
* copying any mutable objects that comprise the internal "deep structure"
* of the object being cloned and replacing the references to these
* objects with references to the copies. If a class contains only
* primitive fields or references to immutable objects, then it is usually
* the case that no fields in the object returned by {@code super.clone}
* need to be modified.
*/
大致意思是,拷贝的对象是独立的,如果包含深层结构(包含对象属性),那么这些引用的对象不会变,即深层结构需要单独处理。
浅拷贝
用代码验证一下浅拷贝
/**
* 铲屎官
*/
class CatOwner implements Cloneable {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
return obj;
}
}
/**
* 肥猫
*/
class FatCat implements Cloneable {
private String name;
private CatOwner catOwner;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public CatOwner getCatOwner() {
return catOwner;
}
public void setCatOwner(CatOwner catOwner) {
this.catOwner = catOwner;
}
public Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
return obj;
}
}
测试一下
public static void main(String[] args) throws CloneNotSupportedException {
// 创建一个铲屎官Alex
CatOwner Alex = new CatOwner();
Alex.setName("Alex");
// 拷贝一个Alex叫Rosie
CatOwner Rosie = (CatOwner) Alex.clone();
// 打印Alex的名称以及地址
System.out.println(Alex.getName() + "::" + Alex);
// 打印Rosie的名称以及地址
System.out.println(Rosie.getName() + "::" + Rosie);
// Alex和Rosie之间的类型比较和内容比较
System.out.println(Alex + "::" + Rosie + "::"
+ Alex.getClass().equals(Rosie.getClass()) + "::" + Alex.equals(Rosie));
Rosie.setName("Rosie");
// 创建一个靓仔
FatCat 靓仔 = new FatCat();
靓仔.setName("靓仔");
// 设置Rosie为靓仔的铲屎官
靓仔.setCatOwner(Rosie);
// 靓仔拷贝出一个扑街仔
FatCat 扑街仔 = (FatCat) 靓仔.clone();
// 打印靓仔的姓名,靓仔的铲屎官姓名,靓仔的地址,靓仔的铲屎官的地址
System.out.println(靓仔.getName() + "::" + 靓仔.getCatOwner().getName()
+ "::" + 靓仔 + "::" + 靓仔.getCatOwner());
// 打印扑街仔的姓名,扑街仔的铲屎官姓名,扑街仔的地址,扑街仔的铲屎官的地址
System.out.println(扑街仔.getName() + "::" + 扑街仔.getCatOwner().getName()
+ "::" + 扑街仔 + "::" + 扑街仔.getCatOwner());
}
输出结果
// 这是创建的Alex
Alex::xxx.CatOwner@6f496d9f
// 这是拷贝Alex的Rosie
Alex::xxx.CatOwner@723279cf
// 类型相同(都是铲屎官),地址不同(两个铲屎官)
xxx.CatOwner@6f496d9f::xxx.CatOwner@723279cf::true::false
// 靓仔和铲屎官Rosie
靓仔::Rosie::xxx.FatCat@1b2c6ec2::xxx.CatOwner@723279cf
// 扑街仔和Rosie,扑街仔是从靓仔拷贝来的,但是保留了铲屎官Rosie的信息,这就是浅拷贝
靓仔::Rosie::xxx.FatCat@4edde6e5::xxx.CatOwner@723279cf
深拷贝
深拷贝需要将靓仔的拷贝方法调整一下,如下:
/**
* 肥猫
*/
class FatCat implements Cloneable {
private String name;
private CatOwner catOwner;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public CatOwner getCatOwner() {
return catOwner;
}
public void setCatOwner(CatOwner catOwner) {
this.catOwner = catOwner;
}
public FatCat clone() throws CloneNotSupportedException {
FatCat cat = (FatCat) super.clone();
// 按照接口说明里,对深层结构做单独处理
cat.setCatOwner((CatOwner) catOwner.clone());
return cat;
}
}
测试代码不变,输出结果如下
靓仔::Rosie::xxx.FatCat@9807454::xxx.CatOwner@723279cf
// @723279cf是Rosie,这里扑街仔的铲屎官已经不是Rosie了
靓仔::Rosie::xxx.FatCat@3d494fbf::xxx.CatOwner@1ddc4ec2
三、结论
浅拷贝:被拷贝的对象中,如果是基本数据类型,则是值传递,如果是引用数据类型,则是引用传递。
深拷贝:被拷贝的对象中,如果是基本数据类型,则是值传递,如果是引用数据类型,则会创建一个新的引用数据类型。