开发者社区> 徐胖子> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Java中的深克隆和浅克隆——Cloneable接口

简介: 一、没有使用克隆带来的问题 public class CloneTest {static Student s = new Student("aaa", 20);// 直接赋值带来的问题public static void noclone(){// 传的是引用的副本,改变了noCloneStudent也改变了sStudent noCloneStudent = new Student();
+关注继续查看
一、没有使用克隆带来的问题
public class CloneTest
{
static Student s = new Student("aaa", 20);

// 直接赋值带来的问题
public static void noclone()
{
// 传的是引用的副本,改变了noCloneStudent也改变了s
Student noCloneStudent = new Student();
noCloneStudent = s;
noCloneStudent.setName("bbb");
noCloneStudent.setAge(21);
System.out.println(s);
System.out.print(noCloneStudent);
}
}
Student [name=bbb, age=21]
Student [name=bbb, age=21]
本意是设置noCloneStudent中的值,但把原来的对象s中的值也改变了。

二、浅克隆与深克隆

①浅克隆——若要克隆Student对象,只克隆他自身以及他包含的所有对象的引用地址。
②深克隆——克隆除自身以外所有的对象,包括自身所包含的所有对象实例。由具体的需求决定深克隆的层次(N层克隆)。

三、浅克隆
public class Student implements Cloneable
{
private String name;
private int age;

public Student()
{
super();
}

public Student(String name, int age)
{
super();
this.name = name;
this.age = age;
}


// 浅克隆
protected Object clone() throws CloneNotSupportedException
{
return super.clone();
}

public String toString()
{
return "Student [name=" + name + ", age=" + age + "]";
}
......
}

public class CloneTest
{
static Student s = new Student("aaa", 20);

// 浅克隆
public static void test0() throws Exception
{
Student ss = (Student) s.clone();
ss.setName("bbb");
ss.setAge(21);
System.out.println(s);
System.out.print(ss);
}
}
Student [name=aaa, age=20]
Student [name=bbb, age=21]
克隆的效果就达到了。

四、深克隆
public class TClass implements Cloneable
{
private Student stu;
private String name;
private List<String> courses = new ArrayList<String>();

public TClass()
{
super();
}

public TClass(Student stu, String name, List<String> courses)
{
super();
this.stu = stu;
this.name = name;
this.courses = courses;
}

// 深克隆
public Object clone() throws CloneNotSupportedException
{
TClass tea = (TClass) super.clone();
tea.stu = (Student) tea.stu.clone();
return tea;
}

public String toString()
{
return "TClass [stu=" + stu + ", name=" + name + ", courses=" + courses + "]";
}
......
}
// 深克隆
public static void test1() throws Exception
{
TClass t = new TClass();
t.setStu(s);
t.setName("张老师");
t.getCourses().add("JAVA");
t.getCourses().add("C#");
System.out.println(t);
TClass tt = (TClass) t.clone();
Student sss = (Student) s.clone();
sss.setName("bbb");
sss.setAge(21);
tt.setStu(sss);
tt.setName("李老师");
tt.getCourses().add("oracle");
tt.getCourses().add("mysql");
System.out.println(t);
System.out.println(tt);
}
TClass [stu=Student [name=aaa, age=20], name=张老师, courses=[JAVA, C#]]
TClass [stu=Student [name=aaa, age=20], name=张老师, courses=[JAVA, C#, oracle, mysql]]
TClass [stu=Student [name=bbb, age=21], name=李老师, courses=[JAVA, C#, oracle, mysql]]
动态数组还是保留了原来的引用,所以其数组没有达到拷贝的效果。

改造一下,让其中的数组有新的引用
public class TClass implements Cloneable
{
private Student stu;
private String name;
private List<String> courses = new ArrayList<String>();

public TClass()
{
super();
}

public TClass(Student stu, String name, List<String> courses)
{
super();
this.stu = stu;
this.name = name;
this.courses = courses;
}

// 深克隆(更深一层)
public Object clone() throws CloneNotSupportedException
{
TClass tea = (TClass) super.clone();
tea.stu = (Student) tea.stu.clone();
tea.courses = new ArrayList<String>(); // 指向不同引用
return tea;
}

public String toString()
{
return "TClass [stu=" + stu + ", name=" + name + ", courses=" + courses + "]";
}
......
}
TClass[stu=Student [name=aaa, age=20], name=张老师, courses=[Java, C#]]
TClass[stu=Student [name=bbb, age=21], name=李老师, courses=[oracle, mysql]]

再改造一下,希望动态数组既有了新的引用,又保留了原值
public class TClass3 implements Cloneable
{
private Student stu;
private String name;
private List<String> courses = new ArrayList<String>();

public TClass()
{
super();
}

public TClass(Student stu, String name, List<String> courses)
{
super();
this.stu = stu;
this.name = name;
this.courses = courses;
}

// 深克隆(更深一层)
public Object clone() throws CloneNotSupportedException
{
TClass tea = (TClass) super.clone();
tea.stu = (Student) tea.stu.clone();
// 指向不同引用
tea.courses = new ArrayList<String>();
// 又想保留原有的值
for (int i = 0; i < courses.size(); i++)
{
tea.courses.add(courses.get(i));
}
return tea;
}

public String toString()
{
return "TClass [stu=" + stu + ", name=" + name + ", courses=" + courses + "]";
}
......

}

Teacher [stu=Student [name=aaa, age=20], name=张老师, courses=[Java, C#]]
Teacher [stu=Student [name=bbb, age=21], name=李老师, courses=[Java, C#, oracle, spring]]

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Java中常用API总结(5)—— Object类中的深克隆和浅克隆
不管对象内部的属性是基本数据类型还是引用数据类型,都完全拷贝过来;基本数据类型拷贝过来的是具体的数据,引用数据类型拷贝过来的是地址值。在Object类中默认的克隆方式就是浅克隆
0 0
Java对象的深克隆与浅克隆(对象复制)(下)
Java对象的深克隆与浅克隆(对象复制)(下)
0 0
Java对象的深克隆与浅克隆(对象复制)(上)
Java对象的深克隆与浅克隆(对象复制)(上)
0 0
Java 深克隆&浅克隆
Java 深克隆(DeepClone)与浅克隆(ShallowClone)是原型设计模式的灵魂。 记录结构: --什么是浅克隆? --实现浅克隆 --什么是深克隆? --实现深克隆 需求 Sunny 软件公司 OA 系统支持工作周报的快速克隆,极大提高了工作周报的编写效率,受到员工的一致好评。
507 0
Java实现单词计数MapReduce
本文分享实现单词计数MapReduce的方法
0 0
JAVA 实现上传图片添加水印(详细版)(上)
JAVA 实现上传图片添加水印(详细版)
0 0
Java 实现汉字按照首字母分组排序
Java 实现汉字按照首字母分组排序
0 0
Java实现图书管理系统
本篇文章是对目前Java专栏已有内容的一个总结练习,希望各位小主们在学习完面向对象的知识后,可以阅览本篇文章后,自己也动手实现一个这样的demo来加深总结应用已经学到知识并进行巩固。
0 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
JAVA 应用排查全景图
立即下载
Java工程师必读手册
立即下载
Java应用提速(速度与激情)
立即下载