参考:
Java如何复制对象
总结:
1.我们平常使用的让一个对象等于另外一个对象,如:
Student a=new Student("A");
Student b=a;
这个复制其实是对对象引用的复制,复制后a和b都指向了堆中的同一个对象,当b修改时a也会跟着被修改。
如
b.setname("B");
System.out.println(a.name);
System.out.println(b.name);
以上输出都是B。可以看到复制的对象和原对象之间是互相影响的。
2.所谓的浅复制,顾名思义就是比较浅的复制,不彻底的复制,当我们浅复制一个对象的时候,我们复制了它的所有的东西,但里面的情况有差别,可以分为两类:
a.所有实例域和不可变类成员对象,比如八种基本数据类型和String类型,这些东西复制之后,在副本中修改不会影响原对象的这些属性的值
b.可变成员对象,如Date对象,还是复制它的引用,也就是说副本和原对象之间还是互相影响的。
举例:
class Student implements Cloneable{
private int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public Object clone() {
Student stu = null;
try{
stu = (Student)super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return stu;
}
}
public class Test {
public static void main(String args[]) {
Student stu1 = new Student();
stu1.setNumber(12345);
Student stu2 = (Student)stu1.clone();
System.out.println("学生1:" + stu1.getNumber());
System.out.println("学生2:" + stu2.getNumber());
stu2.setNumber(54321);
System.out.println("学生1:" + stu1.getNumber());
System.out.println("学生2:" + stu2.getNumber());
}
}
输出:
学生1:12345
学生2:12345
学生1:12345
学生2:54321
这时候我们发现复制1的2修改学号后,1的学号并没有因此而改变,这说明了这些东西都被复制到了一个新的内存空间中。
又比如:
class Address {
private String add;
public String getAdd() {
return add;
}
public void setAdd(String add) {
this.add = add;
}
}
class Student implements Cloneable{
private int number;
private Address addr;
public Address getAddr() {
return addr;
}
public void setAddr(Address addr) {
this.addr = addr;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public Object clone() {
Student stu = null;
try{
stu = (Student)super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return stu;
}
}
public class Test {
public static void main(String args[]) {
Address addr = new Address();
addr.setAdd("杭州市");
Student stu1 = new Student();
stu1.setNumber(123);
stu1.setAddr(addr);
Student stu2 = (Student)stu1.clone();
System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());
System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());
addr.setAdd("西湖区");
System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());
System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());
}
}
输出:
学生1:123,地址:杭州市
学生2:123,地址:杭州市
学生1:123,地址:西湖区
学生2:123,地址:西湖区
这时候发现add成员变量是互相影响的,这种复制就不彻底,对象间还有牵连。
3.所谓的深复制,就是彻底的复制,在浅复制的基础上,使得类中的成员变量复制之后也没有牵连。
@Override
public Object clone() {
Student stu = null;
try{
stu = (Student)super.clone(); //浅复制
stu.addr = (Address)addr.clone(); //深度复制
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return stu;
}
将studen类中的clone方法改成以上就可以了,
网友评论