###浅拷贝
创建一个新对象,然后将当前对象的非静态字段复制到该新对象,如果字段是值类型的, 那么对该字段执行复制;如果该字段是引用类型的话,则复制引用但不复制引用的对象。即如果复制的对象里面的属性为值类型则直接复制值类型过去,如果是引用类型则直接复制地址(不复制对象),所以原对象里面的引用属性如果指向地址改变的话拷贝的对象里面的将不会改变,具体如下面代码所示。(值类型拷贝值,引用类型拷贝地址)
public class MyTest {
public static void main(String[] args) throws InterruptedException, CloneNotSupportedException {
A a = new A();
a.setName("张三");
People p1 = new People();
p1.setA(a);
p1.setB(5);
People p2 = (People) p1.clone();
//因为创建的新对象所以地址不一样,返回false
System.out.println(p1 == p2);
//因为拷贝对象地址,所以返回true
System.out.println(p1.getA() == p2.getA());
System.out.println(p1.getA().getName() + ": " + p1.getB());
System.out.println(p2.getA().getName() + ": " + p2.getB());
a.setName("李四");
p1.setB(10);
//因为此时地址相同,所以p1中的a改变p2中的a也会改变
System.out.println(p1.getA().getName() + ": " + p1.getB());
System.out.println(p2.getA().getName() + ": " + p2.getB());
A a2 = new A();
a2.setName("王五");
p1.setA(a2);
//此时p1中的a变成了新对象,和p2中的a指向的不同的地址
System.out.println(p1.getA().getName() + ": " + p1.getB());
System.out.println(p2.getA().getName() + ": " + p2.getB());
}
}
class A{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class People implements Cloneable {
private A a;
private int b;
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
/**
浅拷贝
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
false
true
张三: 5
张三: 5
李四: 10
李四: 5
false
王五: 10
李四: 5
###深拷贝
public class MyTest {
public static void main(String[] args) throws InterruptedException, CloneNotSupportedException {
A a = new A();
a.setName("张三");
People p1 = new People();
p1.setA(a);
p1.setB(5);
People p2 = (People) p1.clone();
System.out.println(p1 == p2);
System.out.println(p1.getA() == p2.getA());
System.out.println(p1.getA().getName() + ": " + p1.getB());
System.out.println(p2.getA().getName() + ": " + p2.getB());
a.setName("李四");
p1.setB(10);
System.out.println(p1.getA().getName() + ": " + p1.getB());
System.out.println(p2.getA().getName() + ": " + p2.getB());
A a2 = new A();
a2.setName("王五");
p1.setA(a2);
System.out.println(p1.getA().getName() + ": " + p1.getB());
System.out.println(p2.getA().getName() + ": " + p2.getB());
}
}
class A implements Cloneable{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class People implements Cloneable {
private A a;
private int b;
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
@Override
//深拷贝
public Object clone() throws CloneNotSupportedException {
People p = null;
try {
p = (People) super.clone();
} catch (CloneNotSupportedException e) {
System.out.println(e.toString());
}
p.a= (A) a.clone();
return p;
}
}
false
false
张三: 5
张三: 5
李四: 10
张三: 5
王五: 10
张三: 5
可以看出深拷贝拷贝过后的所有对象都和原本的无关,直接为为拷贝的开辟了一片空间。
###直接赋值
我们平常最常用的,即直接p2=p1;这样p1和p2都是同一个对象。