原本写过,后来在阅读的时候,感觉自己都不是太明白了,删除后参考人家的又重新写了一份。

一:开篇

1.复制一个变量

  举例是int类型。

  其他其中七种原始数据类型同样适用。

  原始类型:boolean,char,byte,short,float,double.long

 int apples = 5;
int pears = apples;

2.复制一个对象

 package com.jun.it;

 public class CopyTest {

     public static void main(String[] args) {
Student student1=new Student();
student1.setNumber(123);
//复制
Student student2=student1;
System.out.println("学生1:"+student1.getNumber());
System.out.println("学生2:"+student2.getNumber()); } } class Student{
private int number; public int getNumber() {
return number;
} public void setNumber(int number) {
this.number = number;
} }

3.效果

  

4.接着说明

  上面是一个简单的对象复制,但是这种复制有没有问题,下面添加一行程序:student2.setNumber(456);

  效果就变了,效果如下:

  

  完整的程序:

 package com.jun.it;

 public class CopyTest {

     public static void main(String[] args) {
Student student1=new Student();
student1.setNumber(123);
//复制
Student student2=student1;
student2.setNumber(456);
System.out.println("学生1:"+student1.getNumber());
System.out.println("学生2:"+student2.getNumber()); } } class Student{
private int number; public int getNumber() {
return number;
} public void setNumber(int number) {
this.number = number;
} }

5.结论

  在修改2的时候,1也随着改变了。

  因为在内存堆中是同一个对象。

  这样的复制是有问题的,所以,具体怎么样才能算一个复制对象呢?

  在下面会具体的说明。

二:复制原理的说明

1.Object

  在Object中,有11个方法,有两个projected的方法,其中一个为clone。

  并且clone是一个native方法,说明这是一个供java调用的程序。

  每个类都直接或者间接的父类都是Object,都有clone方法,但是都是projected的,所以不能进行类外进行访问。

  所以,要对对象的复制,就需要对clone方法进行覆盖。

三:为什么要克隆

1.说明

  在引入克隆的示例之后,需要说明为什么要克隆,直接new对象不好么

2.克隆

  克隆的对象可能包含一些已经修改过的属性,而new出来的对象的属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的“状态”就靠clone方法了。

  通过上面的源码都发现了clone是一个native方法,就是快啊,在底层实现的。

  通过clone方法赋值的对象跟原来的对象时同时独立存在的

四:如何克隆

1.克隆的两种方式

  分为浅克隆,和深克隆。

  数据类型主要分为值类型和引用类型。

  浅克隆与深克隆主要的区别在于是否支持引用类型的成员变量的复制。

五:浅克隆

1.步骤

  被复制的类需要实现Clonenable接口

    如果不实现,直接调用clone方法,会抛出CloneNotSupportedException异常

  覆盖clone方法,访问修饰符设置为public。

    在调用super.clone()可以得到需要的复制对象。

2.程序示例

  对刚刚的对象程序,做一个修改。

 package com.jun.it;

 public class CopyTest2 {

     public static void main(String[] args) {
Student2 student1=new Student2();
student1.setNumber(123);
//复制
Student2 student2=(Student2)student1.clone(); System.out.println("学生1:"+student1.getNumber());
System.out.println("学生2:"+student2.getNumber()); student2.setNumber(456);
System.out.println("学生1:"+student1.getNumber());
System.out.println("学生2:"+student2.getNumber()); } } class Student2 implements Cloneable{
private int number; public int getNumber() {
return number;
} public void setNumber(int number) {
this.number = number;
} //clone
public Object clone() {
Student2 stu=null;
try {
stu=(Student2)super.clone();
}catch (Exception e) {
e.printStackTrace();
}
return stu;
} }

3.效果

  这样的复制,已经不再是同一个对象了。

  

六:深度复制

1.对象中有引用一个引用类型的时候

  这个深度复制,是源于上面的浅复制。

  现在,在Student类中加入一个Adress类。

2.程序

  在修改后的程序,观察是否可以做到合适的复制呢?

 package com.jun.it;

 public class CopyTest3 {

     public static void main(String[] args) {
Address address=new Address();
address.setAddress("北京");
Student3 student1=new Student3();
student1.setAddress(address);
//复制
Student3 student2=(Student3)student1.clone(); System.out.println("学生1:"+student1.getAddress().getAddress());
System.out.println("学生2:"+student2.getAddress().getAddress()); address.setAddress("上海"); System.out.println("学生1:"+student1.getAddress().getAddress());
System.out.println("学生2:"+student2.getAddress().getAddress()); } } /**
* Address
* @author dell
*
*/
class Address{
private String address; public String getAddress() {
return address;
} public void setAddress(String address) {
this.address = address;
} }
/**
* Student
* @author dell
*
*/ class Student3 implements Cloneable{
private int number;
private Address address; public int getNumber() {
return number;
} public void setNumber(int number) {
this.number = number;
} public Address getAddress() {
return address;
} public void setAddress(Address address) {
this.address = address;
} //clone
public Object clone() {
Student3 stu=null;
try {
stu=(Student3)super.clone();
}catch (Exception e) {
e.printStackTrace();
}
return stu;
} }

3.效果

  在修改地址后,发现不是合适的复制。

  

4.结论

  原因在浅复制,只是复制了address变量的引用,没有正真的开辟一个新的空间,将复制后再把引用返回给新的对象。

  所以,需要正真的复制对象,而不是纯粹的引用复制。

  可以让Address类可以被复制化,并且修改clone方法。

5.最新的程序

 package com.jun.it;

 public class CopyTest3 {

     public static void main(String[] args) {
Address address=new Address();
address.setAddress("北京");
Student3 student1=new Student3();
student1.setAddress(address);
//复制
Student3 student2=(Student3)student1.clone(); System.out.println("学生1:"+student1.getAddress().getAddress());
System.out.println("学生2:"+student2.getAddress().getAddress()); address.setAddress("上海");
System.out.println("学生1:"+student1.getAddress().getAddress());
System.out.println("学生2:"+student2.getAddress().getAddress()); } } /**
* Address
* @author dell
*
*/
class Address implements Cloneable{
private String address; public String getAddress() {
return address;
} public void setAddress(String address) {
this.address = address;
}
//clone
public Object clone() {
Address address=null;
try {
address=(Address)super.clone();
}catch (Exception e) {
e.printStackTrace();
}
return address;
} }
/**
* Student
* @author dell
*
*/ class Student3 implements Cloneable{
private int number;
private Address address; public int getNumber() {
return number;
} public void setNumber(int number) {
this.number = number;
} public Address getAddress() {
return address;
} public void setAddress(Address address) {
this.address = address;
} //clone
public Object clone() {
Student3 stu=null;
try {
//浅复制
stu=(Student3)super.clone();
}catch (Exception e) {
e.printStackTrace();
}
//深复制
stu.address=(Address)address.clone();
return stu;
} }

6.效果

  

001 Java 深拷贝、浅拷贝及Cloneable接口的更多相关文章

  1. Java 深拷贝、浅拷贝及Cloneable接口

    Cloneable接口是一个空接口,仅用于标记对象,Cloneable接口里面是没有clone()方法,的clone()方法是Object类里面的方法!默认实现是一个Native方法 protecte ...

  2. 深拷贝、浅拷贝与Cloneable接口

    深拷贝与浅拷贝 浅拷贝 public class Student implements Cloneable{ Integer a; Integer b; @Override protected Obj ...

  3. Java深拷贝浅拷贝

    首先,Java中常用的拷贝操作有三个,operator = .拷贝构造函数 和 clone()方法.由于Java不支持运算符重载,我们无法在自己的自定义类型中定义operator=.拷贝构造函数大家应 ...

  4. Java 深拷贝浅拷贝 与 序列化

    一.浅拷贝.深拷贝 浅拷贝会对对象中的成员变量进行拷贝:如果是基本类型,拷贝的就是基本类型的值:如果属性是内存地址(引用类型),拷贝的就是内存地址 : 深拷贝,除了基本类型外,引用类型所引用的对象也会 ...

  5. java 的对象拷贝(有深浅拷贝两种方式,深拷贝实现的两种方式(逐层实现cloneable接口,序列化的方式来实现))

    Java提高篇--对象克隆(复制)(转自:http://www.cnblogs.com/Qian123/p/5710533.html#_label0)   阅读目录 为什么要克隆? 如何实现克隆 浅克 ...

  6. Java clone() 浅拷贝 深拷贝

    假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...

  7. 一步步分析Java深拷贝的两种方式-clone和序列化

    今天遇到一道面试题,询问深拷贝的两种方法.主要就是clone方法和序列化方法.今天就来分析一下这两种方式如何实现深拷贝.如果想跳过解析的朋友,直奔"重点来了!"寻找答案. clon ...

  8. Cloneable接口和Object的clone()方法

    为什么要克隆 为什么要使用克隆,这其实反映的是一个很现实的问题,假如我们有一个对象: public class SimpleObject implements Cloneable { private ...

  9. Java中的Cloneable接口与深拷贝、浅拷贝

    Cloneable接口是一个标记接口,也就是没有任何内容,定义如下: 这里分析一下这个接口的用法,clone方法是在Object种定义的,而且是protected型的,只有实现了这个接口,才可以在该类 ...

随机推荐

  1. DP整理(未完待续)

    一.资源问题 T1 机器分配 已知条件:每家公司分配x台机器的盈利 令f[i][j]表示前i公司分配j台机器的最优解 转移:f[i][j]=max(f[i-1][j-k]+w[i][k]) 初始化:f ...

  2. a标签伪元素选择器

    a{ color: black; } /*未访问的链接*/ a:link{ color: red; } /*访问过的链接*/ a:visited{ color: green; } /*鼠标经过时*/ ...

  3. centos7 源码构建、安装dubbo-monitor

    按照官方文档 ,发现dubbo-monitor-simple-x.x.x-assembly.tar.gz  下载不下来(地址访问不了),那么就自己下载源码构建吧. 我的zookeeper,hadoop ...

  4. 《设计模式》-原则四:接口隔离原则(ISP)

    啊!天气很热啊,回来洗个澡,做个饭吃完后 又出了一身汗,真后悔先洗澡. 加油坚持学习,今天要学的是“接口隔离原则” 意思是说:在设计的时候使用多个专门的接口比使用一个总的接口好很多.一个类对另一个类的 ...

  5. 知名网站内部资料:WEB页面内容优化管理与性能技巧

    回想一下,以前我们不得不花费大量时间去优化页面内容(图片.CSS等等),如今用户有更快速的互联网链接,我们似乎能够使用更大的图像或更大的闪 存文件,里面包含的有视频或者图片.然而,随着移动开发的兴起, ...

  6. Personal idea

    我的设想是在android上开发一款应用程序,整体上是一个指南针的样式,或许你可以称之为一个圆盘,在不同的场景下可以作为不同的功能,指南针,游戏转盘,数字转盘等等.界面可以在不同的情境下更换样式.

  7. Shell脚本-自动化部署反向代理、WEB、nfs

    部署nginx反向代理三个web服务,调度算法使用加权轮询(由于物理原因只开启两台服务器) AutoNginxNfsService.sh #/bin/bash systemctl status ngi ...

  8. git 放弃本地修改操作

      如果在修改时发现修改错误,而要放弃本地修改时, 一, 未使用 git add 缓存代码时. 可以使用 git checkout -- filepathname (比如: git checkout ...

  9. D. Sum in the tree(树形+贪心)

    题目链接;http://codeforces.com/contest/1099/problem/D 题目大意:给出一棵树,每个节点到根节点的路径上经过的所有点的权值之和,其深度为偶数的节点的信息全部擦 ...

  10. 【原创】Linux环境下的图形系统和AMD R600显卡编程(1)——Linux环境下的图形系统简介

    Linux/Unix环境下最早的图形系统是Xorg图形系统,Xorg图形系统通过扩展的方式以适应显卡和桌面图形发展的需要,然而随着软硬件的发展,特别是嵌入式系统的发展,Xorg显得庞大而落后.开源社区 ...