Java对象克隆
来源:互联网 发布:解压缩软件下载免费版 编辑:程序博客网 时间:2024/06/09 15:13
Java对象克隆
1. 介绍
克隆就是复制一个对象的副本。Java支持我们对一个对象进行克隆,通常用在装饰模式和原型模式中。
一个对象中可能有基本数据类型(如:int、long、double等)的属性,也同时含有引用数据类型(如数组、集合等)的属性,所以在对象克隆时分为浅克隆与深克隆两种。那么,什么是浅克隆,什么又是深克隆呢?
浅克隆是指克隆对象时仅仅克隆对象本身(包括对象中的基本类型的变量),而不克隆对象包含的引用指向的子对象,即克隆对象与被克隆对象共享子对象。
深克隆不仅克隆对象本身,而且克隆对象包含的引用指向的所有子对象。
2. clone()方法
Object类中的clone()方法可以实现将对象复制一份并返回给调用者。一般而言,clone()方法满足:
- 对任何的对象obj,都有
obj.clone() != obj
,即克隆对象与原对象不是同一个对象。 - 对任何的对象obj,都有
obj.clone().getClass() == obj.getClass()
,即克隆对象与原对象的类型一样。 - 如果对象obj的equals()方法定义恰当,那么
obj.clone().equals(obj)
应该成立。
Object类的clone()方法执行特定的复制操作,如果此对象的类不能实现接口Cloneable,则会抛出CloneNotSupportedException异常。
在Java中,为了获取对象的一份拷贝,我们可以重写Object类的clone()方法,一般遵循下列步骤:
- 在类中实现Cloneable接口。
- 在类中覆盖基类的clone()方法,并声明为public。
- 在派生类的clone()方法中,调用super.clone()
3. 浅克隆
示例:
地址类:
package test.clone;/** * 地址类 * * @author 小明 * */public class Address implements Cloneable { private String province; // 省 private String city; // 市 private String detail; // 详细地址 public Address() { super(); } public Address(String province, String city, String detail) { super(); this.province = province; this.city = city; this.detail = detail; } 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 getDetail() { return detail; } public void setDetail(String detail) { this.detail = detail; } @Override public String toString() { return "Address [province=" + province + ", city=" + city + ", detail=" + detail + "]"; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); }}
学生类:
package test.clone;/** * 学生类 * * @author 小明 * */public class Student implements Cloneable { private String name; // 姓名 private int age; // 年龄 private Address address; // 地址 public Student() { super(); } public Student(String name, int age, Address address) { super(); this.name = name; this.age = age; this.address = address; } 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() { return "Student [name=" + name + ", age=" + age + ", address=" + address + "]"; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); }}
测试类:
package test.clone;/** * 浅克隆测试 * * @author 小明 * */public class ShallowCloneTest { public static void main(String[] args) throws CloneNotSupportedException { Address address = new Address("广东", "广州", "天河"); // 地址 Student stu1 = new Student("小明", 28, address); // 第一个学生对象 Student stu2 = (Student) stu1.clone(); // 第二个学生对象,为克隆第一个学生对象 // 修改第二个学生对象的信息 stu2.setName("王飞鸿"); stu2.setAge(35); stu2.getAddress().setProvince("四川"); stu2.getAddress().setCity("成都"); stu2.getAddress().setDetail("青羊区"); // 打印第一个学生对象的信息 System.out.println(stu1); }}
运行结果:
Student [name=小明, age=28, address=Address [province=四川, city=成都, detail=青羊区]]
从运行结果看到,我们仅只修改了第二个学生对象的地址,但第一个学生对象的地址也改变了,这说明两个学生对象是共享的学生地址对象。
那如何实现深克隆呢?
4. 深克隆
地址类:
package test.clone;/** * 地址类 * * @author 小明 * */public class Address implements Cloneable { private String province; // 省 private String city; // 市 private String detail; // 详细地址 public Address() { super(); } public Address(String province, String city, String detail) { super(); this.province = province; this.city = city; this.detail = detail; } 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 getDetail() { return detail; } public void setDetail(String detail) { this.detail = detail; } @Override public String toString() { return "Address [province=" + province + ", city=" + city + ", detail=" + detail + "]"; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); }}
学生类:
package test.clone;/** * 学生类 * * @author 小明 * */public class Student implements Cloneable { private String name; // 姓名 private int age; // 年龄 private Address address; // 地址 public Student() { super(); } public Student(String name, int age, Address address) { super(); this.name = name; this.age = age; this.address = address; } 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() { return "Student [name=" + name + ", age=" + age + ", address=" + address + "]"; } @Override public Object clone() throws CloneNotSupportedException { Student stu = (Student) super.clone(); stu.address = (Address) address.clone(); return stu; }}
测试类:
package test.clone;/** * 深克隆测试 * * @author 小明 * */public class DeepCloneTest { public static void main(String[] args) throws CloneNotSupportedException { Address address = new Address("广东", "广州", "天河"); // 地址 Student stu1 = new Student("小明", 28, address); // 第一个学生对象 Student stu2 = (Student) stu1.clone(); // 第二个学生对象,为克隆第一个学生对象 // 修改第二个学生对象的信息 stu2.setName("王飞鸿"); stu2.setAge(35); stu2.getAddress().setProvince("四川"); stu2.getAddress().setCity("成都"); stu2.getAddress().setDetail("青羊区"); // 打印第一个学生对象的信息 System.out.println(stu1); // 打印第二个学生对象的信息 System.out.println(stu2); }}
运行结果:
Student [name=小明, age=28, address=Address [province=广东, city=广州, detail=天河]]Student [name=王飞鸿, age=35, address=Address [province=四川, city=成都, detail=青羊区]]
从运行结果中看出,修改第二个学生对象时,第一个学生对象的地址并不受影响,说明克隆学生对象时,不仅克隆了学生对象,也克隆了其子对象。
5. 利用串行化实现深克隆
地址类:
package test.clone2;import java.io.Serializable;/** * 地址类 * * @author 小明 * */public class Address implements Serializable { private String province; // 省 private String city; // 市 private String detail; // 详细地址 public Address() { super(); } public Address(String province, String city, String detail) { super(); this.province = province; this.city = city; this.detail = detail; } 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 getDetail() { return detail; } public void setDetail(String detail) { this.detail = detail; } @Override public String toString() { return "Address [province=" + province + ", city=" + city + ", detail=" + detail + "]"; }}
学生类:
package test.clone2;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;/** * 学生类 * * @author 小明 * */public class Student implements Serializable { private String name; // 姓名 private int age; // 年龄 private Address address; // 地址 public Student() { super(); } public Student(String name, int age, Address address) { super(); this.name = name; this.age = age; this.address = address; } 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() { return "Student [name=" + name + ", age=" + age + ", address=" + address + "]"; } /** * 利用串行化深克隆 * * @return 深克隆后的对象 */ public Object deepClone() { ObjectOutputStream oos = null; ObjectInputStream ois = null; try { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); oos = new ObjectOutputStream(byteArrayOutputStream); oos.writeObject(this); ois = new ObjectInputStream(new ByteArrayInputStream( byteArrayOutputStream.toByteArray())); return ois.readObject(); } catch (Exception e) { throw new RuntimeException(e); } finally { try { if (oos != null) oos.close(); if (ois != null) ois.close(); } catch (IOException e) { throw new RuntimeException(e); } } }}
测试类:
package test.clone2;/** * 深克隆测试 * * @author 小明 * */public class DeepCloneTest { public static void main(String[] args) throws CloneNotSupportedException { Address address = new Address("广东", "广州", "天河"); // 地址 Student stu1 = new Student("小明", 28, address); // 第一个学生对象 Student stu2 = (Student) stu1.deepClone(); // 第二个学生对象,为克隆第一个学生对象 // 修改第二个学生对象的信息 stu2.setName("王飞鸿"); stu2.setAge(35); stu2.getAddress().setProvince("四川"); stu2.getAddress().setCity("成都"); stu2.getAddress().setDetail("青羊区"); // 打印第一个学生对象的信息 System.out.println(stu1); // 打印第二个学生对象的信息 System.out.println(stu2); }}
运行结果:
Student [name=小明, age=28, address=Address [province=广东, city=广州, detail=天河]]Student [name=王飞鸿, age=35, address=Address [province=四川, city=成都, detail=青羊区]]
说明:利用串行化实现深克隆,克隆对象与子对象对应的类都必须实现java.io.Serializable接口。
- java克隆对象
- java 中克隆对象
- java中的对象克隆
- 浅谈java 对象克隆
- java对象的克隆
- java对象克隆clone
- java 对象 克隆 clone
- Java clone()克隆对象
- java对象的克隆
- JAVA 对象克隆clone
- java对象的克隆
- java 对象的克隆
- java对象克隆简介
- 模拟Java对象克隆
- Java克隆对象
- Java对象深度克隆
- java对象克隆clone
- JAVA对象的克隆
- hadoop学习笔记
- ACdream 1113 The Arrow (概率dp求期望)
- Uoj#9感想
- listView中监听冲突问题(以及view里tag的使用)
- 开篇记
- Java对象克隆
- POJ_2029_GetManyPersimmonTrees
- 使用Xcode实现第一个C语言程序——Hello world
- 【POJ 1442】 Black Box
- 2.1 window的基本概念和用法
- 左右手坐标系区别和联系
- 2.2 视图的基本概念
- hive命令行不打印日志
- 2.3 视图的层次关系