对象的拷贝
创建一个Person对象 里面有两个属性 name 与 age
package arrayList.src.JavaSE.Study.Studay02;
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
在Test类中设置分别设置两个属性的值
Person person = new Person();
person.setName("小明");
person.setAge(23);
此时内存模型图为:
当再声明一个Person类型的对象,并且指向了同一块内存空间,并且重新设置一下他们的属性,此时内存模型的图为:
Person person1 = person;
person1.setAge(44);
person1.setName("小红");
从此图中我们可以分析得知,不仅仅刚刚声明对象的属性改了,一开始创建对象的属性也进行了更改。是不是这样呢?
Person person = new Person();
person.setName("小明");
person.setAge(23);
Person person1 = person;
System.out.println(person.hashCode());
System.out.println(person1.hashCode());
person1.setAge(44);
person1.setName("小红");
System.out.println(person1.toString());
System.out.println(person.toString());
为什么要用克隆(拷贝)
克隆的对象可能包含一些已经修改过的属性,而 new 出来的对象的属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的“状态”就靠克隆方法了。
浅克隆
1:在类中实现Cloneable接口,重写clone()方法
package arrayList.src.JavaSE.Study.Studay02;
public class Person implements Cloneable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected Person clone() throws CloneNotSupportedException { //这里值得注意要改成Person类型默认是Object类型的
return (Person) super.clone();
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
2、在新声明对象中直接指向克隆出来的引用
Person person1 = person.clone();
再次重新设置属性并且输出当前对象的属性与之前 的对象的属性
try {
Person person1 = person.clone();
person1.setName("小红");
person1.setAge(45);
System.out.println(person1.toString());
System.out.println(person.toString());
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
结果
此时内存模型的图为
深克隆(深拷贝)
上面所提到的深拷贝Person类中所有属性全为基本数据类型,可实际开发中一个实体类不可能只存在基本数据类型,但是存在引用数据类型该怎么办,此时就需要深拷贝
重新定义Person类name 、age属性再定义一个Water实类。
package arrayList.src.JavaSE.Study.Studay02;
public class Person implements Cloneable {
private String name;
private int age;
private Water water;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
Water类
public class Water {
private int WaterVolume = 40; //水量
public int getWaterVolume() {
return WaterVolume;
}
@Override
public String toString() {
return "Water{" +
"WaterVolume=" + WaterVolume +
'}';
}
public void setWaterVolume(int waterVolume) {
WaterVolume = waterVolume;
}
}
Test类实例化water对象并设置属性值30;再声明为water1指向water设置属性50
public class Test {
public static void main(String[] args) {
Person person = new Person();
Water water = new Water();
water.setWaterVolume(30);
person.setName("小明");
person.setAge(23);
person.setWater(water);
try {
Water water1 = water;
water1.setWaterVolume(50);
Person person1 = person.clone();
person1.setName("小红");
person1.setAge(45);
person1.setWater(water1);
System.out.println("拷贝后的:"+person1.toString());
System.out.println("拷贝前的"+person.toString());
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
此时运行结果:
发现,Water的值被改变了?
于是我们进行如下操作
再原有的Water类中实现Cloneable接口,实现返回Water类型clone方法,Test类修改为
Water water1 = water.clone();
结果:
内存模型: