浅拷贝
浅拷贝是使用默认clone()方法得到一个成员值完全一致的类对象
拷贝对象成员赋新值修改持有的引用地址,对象成员修改引用对象实际修改内存地址
public class Copy implements Cloneable { private int iNum; public Integer INum; public Reference Ref; public String str; // getters and setters @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } public static void main(String[] args) throws CloneNotSupportedException { test1(); test2(); test3(); test4(); test5(); } }
浅拷贝时在堆中生成一个新对象
可见如下两个对象的内存地址不同,source和clone引用的是不同的对象
public Copy() {}
private static void test1() throws CloneNotSupportedException {
Copy source = new Copy();
System.out.println(source);
Copy clone = (Copy) source.clone();
System.out.println(clone);
}
copy.Copy@1b6d3586
copy.Copy@4554617c
浅拷贝基本类型成员仅拷贝值
浅拷贝时,基本类型成员变量仅复制值到自己的内存空间
public Copy(int iNum) {
this.iNum = iNum;
}
private static void test2() throws CloneNotSupportedException {
Copy source = new Copy(1);
Copy clone = (Copy) source.clone();
System.out.println(source.iNum + "|" + clone.iNum);
source.setiNum(2);
System.out.println(source.iNum + "|" + clone.iNum);
clone.setiNum(2);
System.out.println(source.iNum + "|" + clone.iNum);
}
1|1
2|1
2|2
浅拷贝引用类型成员仅拷贝引用
对象中的引用类型成员在浅拷贝时,仅拷贝内存地址(即引用),若修改内存地址(即修改引用对象内容)将同时影响原对象和拷贝对象
public Copy(Reference ref) {
Ref = ref;
}
public static void test3() throws CloneNotSupportedException {
Reference reference = new Reference("s0");
Copy source = new Copy(reference);
Copy clone = (Copy) source.clone();
System.out.println(source.Ref + "|" + clone.Ref);
source.getRef().setString("s1");
System.out.println(source.getRef().getString() + "|" + clone.getRef().getString());
clone.getRef().setString("s2");
System.out.println(source.getRef().getString() + "|" + clone.getRef().getString());
}
copy.Reference@74a14482|copy.Reference@74a14482
s1|s1
s2|s2
原对象和拷贝对象修改引用互不影响
对象中的引用类型成员发生引用修改时,实际更改的是 对象自己持有的引用内存地址,因此相互不影响
public static void test4() throws CloneNotSupportedException {
Copy source = new Copy(new Integer(0));
Copy clone = (Copy) source.clone();
System.out.println(source.getINum() + "|" + clone.getINum());
source.setINum(new Integer(1));
System.out.println(source.getINum() + "|" + clone.getINum());
clone.setINum(new Integer(2));
System.out.println(source.getINum() + "|" + clone.getINum());
}
0|0
1|0
1|2
浅拷贝不可变成员对象的解释
不可变对象的修改结果是新对象,指向新引用,所以互不影响
public Copy(String str) {
this.str = str;
}
public static void test5() throws CloneNotSupportedException {
String s0 = new String("s0");
Copy source = new Copy(s0);
Copy clone = (Copy) source.clone();
System.out.println(source.str + "|" + clone.str);
source.setStr(s0 + "a");
System.out.println(source.str + "|" + clone.str);
clone.setStr(clone.getStr() + "b");
System.out.println(source.str + "|" + clone.str);
}
s0|s0
s0a|s0
s0a|s0b
深拷贝
深拷贝是生成一个与原对象内存结构完全相同,但成员变量完全无关的新对象。意味着深拷贝的 引用类型成员均指向独立的新对象,与原引用指向地址不同
实现方法
1)额外开辟内存空间,逐项复制填写值
2)在浅拷贝基础上,递归的将所有 引用类型成员也进行clone()拷贝
3)采用 序列化方法