三种拷贝方法
引用拷贝是拷贝变量的引用,浅拷贝在堆中创建一个新的对象,但是对象内部的引用还是指向同一个地址。深拷贝就是完全全新的变量。下面用一个例子展示。
class Tree implements Cloneable{
public String name;
public Tree(String name) {
this.name = name;
}
@Override
public Tree clone() throws CloneNotSupportedException {
return (Tree) super.clone();
}
}
class Fruit implements Cloneable{
public String name;
public Tree tree;
public Fruit(String name, Tree tree) {
this.name = name;
this.tree = tree;
}
@Override
public Fruit clone() {
try {
return (Fruit) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
public void print() {
System.out.println(name + "长在" + tree.name + "上");
}
}
public class TestCopy {
public static void main(String[] args) {
// 引用
System.out.println("***引用拷贝***");
Fruit apple = new Fruit("苹果", new Tree("苹果树"));
apple.print();
Fruit apple1 = apple;
apple1.tree = new Tree("香蕉树");
apple1.print();
apple.print();
// 浅拷贝
System.out.println("***浅拷贝***");
Fruit apple2 = new Fruit("苹果", new Tree("苹果树"));
apple2.print();
Fruit banana2 = apple2.clone();
banana2.name = "香蕉";
System.out.println(apple2.tree == banana2.tree);
banana2.tree = new Tree("香蕉树");
banana2.print();
apple2.print();
}
}
首先在引用拷贝中,添加了一个新的苹果(apple1),它由用引用拷贝创建,当修apple1.tree时由于是引用复制,导致apple.tree也被修改。
其次在浅拷贝中,name和tree都创建了新的引用,虽然在创建之初指向的地址还是相同的,但是后续修改的时候会指向新的地址。例如new了一棵香蕉树,因为香蕉是浅拷贝,内部的tree在是新创建的,引用指向香蕉树的时候并不会影响苹果。所以苹果还是长在苹果树上,而香蕉则长在香蕉树上。另外,通过apple2.tree==banana2.tree可以发现,在浅拷贝之初指向的地址确实是同一个,这也是浅拷贝跟深拷贝不同之一。
深拷贝则是创建两个完全相互独立的变量。