假克隆:
我觉得就是一个引用操作,不过注意引用类型的参数在源对象被改变后,假克隆的对象也会被改变
浅克隆:
这个需要注意的是 浅克隆 对基本数据类型和不可变类对象的是可以进行的,但是是可变的引用类型需要使用深克隆
首先类需要实现Cloneable接口
并且要实现clone方法 需要重写父类的clone方法
因为父类的protocol类型修饰 如果要在其他包使用 需要改成public类型
整个浅克隆的类代码如下:
package method;
import java.util.Objects;
public class OverrideHash implements Cloneable {
private int id;
private String name;
private int age;
private int gender;
public OverrideHash() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OverrideHash that = (OverrideHash) o;
return id == that.id &&
age == that.age &&
gender == that.gender &&
Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name, age, gender);
}
@Override
public OverrideHash clone() {
OverrideHash overrideHash = null;
try {
overrideHash = (OverrideHash) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return overrideHash;
}
@Override
public String toString() {
return "OverrideHash{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
'}';
}
}
这里可以和假克隆一起做个栗子 比较下
最后得到结论是:
很明显看到在两个克隆对象后面修改了原对象的一个参数,假克隆的对应参数被修改了,而浅克隆的没有。
深克隆:
深克隆的条件时如果需要克隆的对象的参数中包括了可变引用类型,则在克隆时使用深克隆
直接举个栗子:
一个只有基本数据类型和不可变的引用类型 address类
public class Address implements Cloneable {
private int id;
private String contry;
private String province;
private String city;
private String street;
public Address(int id, String contry, String province, String city, String street) {
this.id = id;
this.contry = contry;
this.province = province;
this.city = city;
this.street = street;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getContry() {
return contry;
}
public void setContry(String contry) {
this.contry = contry;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Address address = (Address) o;
return id == address.id &&
Objects.equals(contry, address.contry) &&
Objects.equals(province, address.province) &&
Objects.equals(city, address.city) &&
Objects.equals(street, address.street);
}
@Override
public int hashCode() {
return Objects.hash(id, contry, province, city, street);
}
@Override
public Object clone() {
Address address = null;
try {
address = (Address) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return address;
}
@Override
public String toString() {
return "Address{" +
"id=" + id +
", contry='" + contry + '\'' +
", province='" + province + '\'' +
", city='" + city + '\'' +
", street='" + street + '\'' +
'}';
}
}
再来个user对象,用于深克隆
public class User implements Cloneable {
private int id;
private String name;
private int age;
private int gender;
private Address address;
public User(int id, String name, int age, int gender, Address address) {
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return id == user.id &&
age == user.age &&
gender == user.gender &&
Objects.equals(name, user.name) &&
Objects.equals(address, user.address);
}
@Override
public int hashCode() {
return Objects.hash(id, name, age, gender, address);
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
", address=" + address.toString() +
'}';
}
@Override
public Object clone() {
User user = null;
try {
user = (User) super.clone();
user.address = (Address) address.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return user;
}
}
注意得到的是 user在克隆的时候将Address对象单独进行了一次克隆。
这样才能保证address对象的参数克隆过去
举个栗子尝试下:
得到的结果:
引用对象也克隆成功了
如果 不将Address对象克隆会怎样呢?
地址信息克隆失败,直接引用过去了。
还有一个问题,使用序列化也可以实现"克隆",就是将 克隆的类序列化 ,然后将其保存到硬盘,再从硬盘中读取出来存到一个新的对象当中去。
不过效率低于克隆