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()方法方便輸出該類的對象,代碼如下:
地址對象:
package com.nf147.Constroller; public class Address implements Cloneable { private String state; //國家 private String province; //省 private String city; //市 public Address() { } public Address(String state, String province, String city) { this.state = state; this.province = province; this.city = city; } public String getState() { return state; } public void setState(String state) { this.state = state; } 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; } @Override public String toString() { //重寫toString StringBuilder sb=new StringBuilder(); sb.append("國家:"+state+","); sb.append("省:"+province+","); sb.append("市:"+city+","); return sb.toString(); } }
編寫Employee 類,首先在該類中定義name(表示姓名)、age(表示年齡)和address(表示地址)3 個域,然后在構造方法中初始化這3 個域,並提供getter()和setter()方法用於獲得和修改這3 個域,再重寫toString()方法方便輸出該類的對象,最后重寫clone()方法來提供克隆的功能,代碼如下:
員工:
package com.nf147.Constroller; public class Employee implements Cloneable { private String name; //姓名 private int age; //年齡 private Address address; //地址 public Employee(String name, int age, Address address) { this.name = name; this.age = age; this.address = address; } public Employee() { } 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 Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Override public 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(); } return employee; } }
測試類:
package com.nf147.Constroller; public class TestClone { public static void main(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); } }
截圖:
說明:
從圖中可以看到,對於引用類型並沒有克隆成功。
2.深克隆(1)編寫類Address1,在該類中首先定義state(表示國家)、province(表示省)和city(表示市)3 個域,然后在構造方法中初始化這3 個域,並提供了getter()和setter()方法用於獲得和修改這3 個域,再重寫toString()方法方便輸出該類的對象,最后重寫clone()方法提供克隆的功能,關鍵代碼如下:
package com.nf147.Constroller; public class Address implements Cloneable { private String state; //國家 private String province; //省 private String city; //市 public Address() { } public Address(String state, String province, String city) { this.state = state; this.province = province; this.city = city; } public String getState() { return state; } public void setState(String state) { this.state = state; } 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; } @Override public String toString() { //重寫toString StringBuilder sb=new StringBuilder(); sb.append("國家:"+state+","); sb.append("省:"+province+","); sb.append("市:"+city+","); return sb.toString(); } @Override protected Address clone(){ Address address = null; try{ address=(Address)super.clone(); }catch (CloneNotSupportedException e){ e.printStackTrace(); } return address; } }
說明:
Address 類的域不是基本類型就是不可變類型,所以可以直接使用淺克隆。
(2)編寫Employee類,首先在該類中定義name(表示姓名)、age(表示年齡)和address(表示地址)3 個域,然后在構造方法中初始化這3 個域,並提供getter()和setter()方法用於獲得和修改這3 個域,再重寫toString()方法方便輸出該類的對象,最后重寫clone()方法來提供克隆的功能。代碼如下:
package com.nf147.Constroller; public class Employee implements Cloneable { private String name; //姓名 private int age; //年齡 private Address address; //地址 public Employee(String name, int age, Address address) { this.name = name; this.age = age; this.address = address; } public Employee() { } 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 Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Override public 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(); } return employee; } }
測試:
package com.nf147.Constroller; public class TestClone { public static void main(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); } }
截圖: