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); } }