JAVA复制
java 复制就是将一个对象的引用复制到另一个对象。主要有三种方式,第一种是直接赋值,第二种是浅拷贝,第三种是深拷贝
直接赋值
a1 = a2
直接赋值复制的仅仅是引用,也就是a1和a2指向的是用一个对象。当a1变化时,a2也跟着变化。
浅拷贝
- 如果拷贝的对象是值类型,将赋值给给克隆对象,在堆中有独立的内存
- 如果拷贝的对象是引用类型,则将引用对象的地址复制给克隆对象,两个对象指向相同的地址
Person类
class Person implements Cloneable{
private Integer age ;
private String name ;
private Student student;
@Override
protected Object clone() throws CloneNotSupportedException {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public Person(Integer age, String name, Student student) {
this.age = age;
this.name = name;
this.student = student;
}
public Person() {
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student getStudent() {
return student;
}
public void setStudent(String name) {
this.student.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
", student=" + student +
'}';
}
}
Student类
class Student {
public Student() {
}
public Student(String name) {
this.name = name;
}
String name = "zx";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
}
测试
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person(18, "jx", new Student("zx"));
Person p2 = (Person)p1.clone();
System.out.println(p1);
System.out.println(p2);
p1.setName("xx");
p1.setAge(19);
p1.setStudent("wz");
System.out.println(p1);
System.out.println(p2);
}
}
输出结果
Person{age=18, name='jx', student=Student{name='zx'}}
Person{age=18, name='jx', student=Student{name='zx'}}
Person{age=19, name='xx', student=Student{name='wz'}}
Person{age=18, name='jx', student=Student{name='wz'}}
浅拷贝之后,两个对象的结果相同。
改变p1的成员属性值后,p2的student属性随之改变,而age和name属性却没有发生变化。因为当改变如Integer、String这类不可变的对象时,会在内存中生成一个新的对象来存放新的值,所以p1的name和age指向了新的地址,但p2的并没有改变。
深拷贝
深拷贝不仅复制对象本身,还复制对象所包含的引用所指向的所有的对象
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person(18, "jx", new Student("zx"));
Person p2 = (Person)p1.clone();
System.out.println(p1);
System.out.println(p2);
p1.setName("xx");
p1.setAge(19);
p1.setStudent("wz");
System.out.println(p1);
System.out.println(p2);
}
}
class Person implements Cloneable{
private Integer age ;
private String name ;
private Student student;
@Override
protected Object clone() throws CloneNotSupportedException {
try {
Person person = (Person)super.clone();
person.student = (Student)student.clone();
return person;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public Person(Integer age, String name, Student student) {
this.age = age;
this.name = name;
this.student = student;
}
public Person() {
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student getStudent() {
return student;
}
public void setStudent(String name) {
this.student.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
", student=" + student +
'}';
}
}
class Student implements Cloneable{
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Student() {
}
public Student(String name) {
this.name = name;
}
String name = "zx";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
}
最后的结果
Person{age=18, name='jx', student=Student{name='zx'}}
Person{age=18, name='jx', student=Student{name='zx'}}
Person{age=19, name='xx', student=Student{name='wz'}}
Person{age=18, name='jx', student=Student{name='zx'}}