Java中常用的拷贝操作有三个,operator=、拷贝构造函数和clone()方法。
由于Java不支持运算符重载,我们无法在自定义类型中定义operator=,所以使用operator=获取的对象都是浅拷贝,若要实现深拷贝那只能借助于拷贝构造函数和clone方法。
这里我们先看一个基本的原则关系图,掌握了这些基本原则,我们就可以比较好的掌握深拷贝和浅拷贝的概念了。
下面是一个具体的实现例子:
package com.basic.clone;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BasicClone {
public static void main(String argv[]) {
Person p = new Person();
p.setAge(20);
p.setName("lee");
int[] number = {1,2,3,4,5};
p.setNumber(number);
Person p1 = p;
Person p2 = (Person)p.clone();
Person p3 = new Person(p);
System.out.println(p.getNumber()[0] + " " + p1.getNumber()[0] + " " + p2.getNumber()[0] + " " + p3.getNumber()[0]);
int[] new_number = p2.getNumber();
new_number[0] = 5;
p2.setNumber(new_number);
int[] n = p3.getNumber();
n[0] = 10;
p3.setNumber(n);
System.out.println(p.getNumber()[0] + " " + p1.getNumber()[0] + " " + p2.getNumber()[0] + " " + p3.getNumber()[0]);
List<Person> list1 = new ArrayList<Person>();
list1.add(p);
List<Person> list2 = new ArrayList<Person>(list1);
list2.get(0).setName("zhang");
System.out.println(list1.get(0).getName());
}
}
class Person implements Cloneable {
private int age;
private String name;
private int[] number;
public Person() {
}
public Person(Person p) {
this.age = p.age;
this.name = p.name;
this.number = Arrays.copyOf(p.number, p.number.length);
}
@Override
public Object clone() {
Person sc = new Person();
sc.age = this.age;
sc.name = this.name;
sc.number = Arrays.copyOf(this.number, this.number.length);
return sc;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int[] getNumber() {
return number;
}
public void setNumber(int[] number) {
this.number = number;
}
}
输出结果:
1 1 1 1
1 1 5 10
zhang
最后总结,两点特别注意的地方。
1)如果自定义类型里面还有自定义类型的属性,则这个属性也必须实现自己的拷贝构造函数和clone方法。
2)预定义的集合类型,若元素是自定义类型的话,是无法实现深拷贝的。因为集合类型的拷贝构造函数和clone方法调用的知识元素的operator=操作符,
但是自定义的类型无法通过operator=实现深拷贝。