假克隆:
我覺得就是一個引用操作,不過注意引用類型的參數在源對象被改變後,假克隆的對象也會被改變
淺克隆:
這個需要注意的是 淺克隆 對基本數據類型和不可變類對象的是可以進行的,但是是可變的引用類型需要使用深克隆
首先類需要實現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對象克隆會怎樣呢?
地址信息克隆失敗,直接引用過去了。
還有一個問題,使用序列化也可以實現"克隆",就是將 克隆的類序列化 ,然後將其保存到硬盤,再從硬盤中讀取出來存到一個新的對象當中去。
不過效率低於克隆