java為什麼要 對象克隆:
在程式開發時,有時可能會遇到以下情況:已經存在一個對象A,現在需要一個與A對象完全相同的B 對象,并對B 對象的屬性值進行修改,但是A 對象原有的屬性值不能改變。這時,如果使用Java 提供的對象指派語句,當修改B 對象的屬性值後,A 對象的屬性值也将被修改。那麼應該如何實作建立一個與A 對象完全相同的B 對象,但是改變B對象的屬性值時A 對象的屬性值不變呢?
專家解答
要實作這一功能,可以使用Object 類中的clone()方法。clone()方法可以用來完成對象的淺克隆。所謂淺克隆就是說被克隆的對象各個屬性都是基本類型,而不是引用類型。如果存在引用類型的屬性,則需要進行深克隆。下面對這兩種克隆方式進行舉例說明。
1.淺克隆(1)編寫Address 類,首先在該類中定義state(表示國家)、province(表示省)和city(表示市)3 個域,然後在構造方法中初始化這3 個域,并提供getter()和setter()方法用于獲得和修改這3 個域,最後重寫toString()方法友善輸出該類的對象,代碼如下:
1.淺克隆(1)編寫Address 類,首先在該類中定義state(表示國家)、province(表示省)和city(表示市)3 個域,然後在構造方法中初始化這3 個域,并提供getter()和setter()方法用于獲得和修改這3 個域,最後重寫toString()方法友善輸出該類的對象,代碼如下:
位址對象:
packagecom.nf147.Constroller;public class Address implementsCloneable {private String state; //國家
private String province; //省
private String city; //市
publicAddress() {
}publicAddress(String state, String province, String city) {this.state =state;this.province =province;this.city =city;
}publicString getState() {returnstate;
}public voidsetState(String state) {this.state =state;
}publicString getProvince() {returnprovince;
}public voidsetProvince(String province) {this.province =province;
}publicString getCity() {returncity;
}public voidsetCity(String city) {this.city =city;
}
@Overridepublic String toString() { //重寫toString
StringBuilder sb=newStringBuilder();
sb.append("國家:"+state+",");
sb.append("省:"+province+",");
sb.append("市:"+city+",");returnsb.toString();
}
}
編寫Employee 類,首先在該類中定義name(表示姓名)、age(表示年齡)和address(表示位址)3 個域,然後在構造方法中初始化這3 個域,并提供getter()和setter()方法用于獲得和修改這3 個域,再重寫toString()方法友善輸出該類的對象,最後重寫clone()方法來提供克隆的功能,代碼如下:
員工:
packagecom.nf147.Constroller;public class Employee implementsCloneable {private String name; //姓名
private int age; //年齡
private Address address; //位址
public Employee(String name, intage, Address address) {this.name =name;this.age =age;this.address =address;
}publicEmployee() {
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}public intgetAge() {returnage;
}public void setAge(intage) {this.age =age;
}publicAddress getAddress() {returnaddress;
}public voidsetAddress(Address address) {this.address =address;
}
@Overridepublic String toString() { //重新toString()方法
return "Employee{" +
"姓名='" + name + '\'' +
", 年齡=" + age +
", 位址=" + address +
'}';
}public Employee clone() { //實作淺克隆
Employee employee = null;try{
employee= (Employee) super.clone();
employee.address=address.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}returnemployee;
}
}
測試類:
packagecom.nf147.Constroller;public classTestClone {public static voidmain(String[] args) {
System.out.println("克隆之前:");
Address address= new Address("中國", "吉林", "長春");
Employee employee1= new Employee("無語", 32, address);
System.out.println("員工 1 的資訊");
System.out.println(employee1);
System.out.println("====================");
System.out.println("克隆之後:");
Employee employee2=employee1.clone();
employee2.getAddress().setState("中國");
employee2.getAddress().setProvince("遼甯");
employee2.getAddress().setCity("大連");
employee2.setName("傾城");
employee2.setAge(33);
System.out.println("員工2 的 資訊");
System.out.println(employee2);
System.out.println("員工1的 資訊");
System.out.println(employee1);
}
}
截圖:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5CM5cTO2IDN5IDN0EmMzIDM4YTNxczM4IzNwkjY5YDOj9CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
說明:
從圖中可以看到,對于引用類型并沒有克隆成功。
2.深克隆(1)編寫類Address1,在該類中首先定義state(表示國家)、province(表示省)和city(表示市)3 個域,然後在構造方法中初始化這3 個域,并提供了getter()和setter()方法用于獲得和修改這3 個域,再重寫toString()方法友善輸出該類的對象,最後重寫clone()方法提供克隆的功能,關鍵代碼如下:
packagecom.nf147.Constroller;public class Address implementsCloneable {private String state; //國家
private String province; //省
private String city; //市
publicAddress() {
}publicAddress(String state, String province, String city) {this.state =state;this.province =province;this.city =city;
}publicString getState() {returnstate;
}public voidsetState(String state) {this.state =state;
}publicString getProvince() {returnprovince;
}public voidsetProvince(String province) {this.province =province;
}publicString getCity() {returncity;
}public voidsetCity(String city) {this.city =city;
}
@Overridepublic String toString() { //重寫toString
StringBuilder sb=newStringBuilder();
sb.append("國家:"+state+",");
sb.append("省:"+province+",");
sb.append("市:"+city+",");returnsb.toString();
}
@OverrideprotectedAddress clone(){
Address address= null;try{
address=(Address)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}returnaddress;
}
}
說明:
Address 類的域不是基本類型就是不可變類型,是以可以直接使用淺克隆。
(2)編寫Employee類,首先在該類中定義name(表示姓名)、age(表示年齡)和address(表示位址)3 個域,然後在構造方法中初始化這3 個域,并提供getter()和setter()方法用于獲得和修改這3 個域,再重寫toString()方法友善輸出該類的對象,最後重寫clone()方法來提供克隆的功能。代碼如下:
packagecom.nf147.Constroller;public class Employee implementsCloneable {private String name; //姓名
private int age; //年齡
private Address address; //位址
public Employee(String name, intage, Address address) {this.name =name;this.age =age;this.address =address;
}publicEmployee() {
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}public intgetAge() {returnage;
}public void setAge(intage) {this.age =age;
}publicAddress getAddress() {returnaddress;
}public voidsetAddress(Address address) {this.address =address;
}
@Overridepublic String toString() { //重新toString()方法
return "Employee{" +
"姓名='" + name + '\'' +
", 年齡=" + age +
", 位址=" + address +
'}';
}public Employee clone() { //實作淺克隆
Employee employee = null;try{
employee= (Employee) super.clone();
employee.address=address.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}returnemployee;
}
}
測試:
packagecom.nf147.Constroller;public classTestClone {public static voidmain(String[] args) {
System.out.println("克隆之前:");
Address address= new Address("中國", "吉林", "長春");
Employee employee1= new Employee("無語", 32, address);
System.out.println("員工 1 的資訊");
System.out.println(employee1);
System.out.println("====================");
System.out.println("克隆之後:");
Employee employee2=employee1.clone();
employee2.getAddress().setState("中國");
employee2.getAddress().setProvince("遼甯");
employee2.getAddress().setCity("大連");
employee2.setName("傾城");
employee2.setAge(33);
System.out.println("員工2 的 資訊");
System.out.println(employee2);
System.out.println("員工1的 資訊");
System.out.println(employee1);
}
}
截圖: