一.JAVA假克隆

Java中,对于基本类型,可以用“=”进行克隆,而对于引用类型却不能简单的使用“=”进行克隆,这与JAVA的内存使用空间有关,JAVA在栈中保存基本类型和引用变量,在堆中保存对象。对于引用变量而言,使用“=”将修改引用,而不是复制堆中的对象,此时两个引用对象将指向同一个对象,因此如果对一个变量修改则会修改另一个对象。

public class Employee {
private String name;
private int age;
//省略get和set方法
@Override
public String toString() {
return "姓名:" + name + ", 年龄:" + age;
}
}
public class Test {
public static void main(String[] args) {
System.out.println("克隆之前:");
Employee employee1 = new Employee();
employee1.setName("芋头1");
employee1.setAge(12);
System.out.println("员工1的信息:");
System.out.println(employee1);
System.out.println("克隆之后:");
Employee employee2 = employee1;
employee2.setName("芋头2");
employee2.setAge(114);
System.out.println("员工2的信息:");
System.out.println(employee2);
System.out.println("员工1的信息:");
System.out.println(employee1);
}
}

输出:
克隆之前:
员工1的信息:
姓名:芋头1, 年龄:12
克隆之后:
员工2的信息:
姓名:芋头2, 年龄:114
员工1的信息:
姓名:芋头2, 年龄:114
可以看出,employee1和employ2两个引用变量同时指向一个对象,当修改employee2的域时,employee11的域也被修改,因此是假克隆。
二、浅克隆
protect Object clone() 
通常需要改写该方法并把访问权限限定为public,该方法对于类中的每个域,如果只包含基本类型和不可变的引用类型,如string,或者对象在其生命周期内不可变化,则可以用浅克隆来复制对象。

 public class Address {
private String state;
private String province;
private String city;
//省略get和set
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("国家:" + state + ", ");
sb.append("省:" + province + ", ");
sb.append("市:" + city);
return sb.toString();
}
} public class Employee implements Cloneable {
private String name;
private int age;
private Address address;
//省略get和set
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("姓名:" + name + ", ");
sb.append("年龄:" + age + "\n");
sb.append("地址:" + address);
return sb.toString();
} @Override
public Employee clone() {
Employee employee = null;
try {
employee = (Employee) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return employee;
}
} public class Test {
public static void main(String[] args) {
System.out.println("克隆之前:");
Address address = new Address("中国", "吉林", "长春");
Employee employee1 = new Employee("明日科技", 12, address);
System.out.println("员工1的信息:");
System.out.println(employee1);
System.out.println("克隆之后:");
Employee employee2 = employee1.clone();
employee2.getAddress().setState("中国");
employee2.getAddress().setProvince("四川");
employee2.getAddress().setCity("成都");
employee2.setName("西南交通大学");
employee2.setAge(114);
System.out.println("员工2的信息:");
System.out.println(employee2);
System.out.println("员工1的信息:");
System.out.println(employee1);
}
}

输出:

克隆之前:
员工1的信息:
姓名:明日科技, 年龄:12
地址:国家:中国, 省:吉林, 市:长春
克隆之后:
员工2的信息:
姓名:西南交通大学, 年龄:114
地址:国家:中国, 省:四川, 市:成都
员工1的信息:
姓名:明日科技, 年龄:12
地址:国家:中国, 省:四川, 市:成都

我们发现,employee类中又包含了Adress类adress的引用,我们知道,clone方法默认的是浅克隆,即不会克隆对象引用的对象,而只是简单地复制这个引用。所以在上例中,adress对象在内存中只有一个,employee1和employee2都指向它,任何一个对象对它的修改都会影响另一个对象。所以adress的值也被修改了。
三,深克隆

一种就是在引用类型中添加克隆方法。如对上面的浅克隆代码改成:

在Adress类中增加

protected Address clone() {
Address address = null;
try {
address = (Address) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return address;
}

Employee中:

public Employee clone() {

Employee employee = null;

try {

employee = (Employee) super.clone();

employee.address = address.clone();

} catch (CloneNotSupportedException e) {

e.printStackTrace();

}

输出:
克隆之前:
员工1的信息:
姓名:明日科技, 年龄:12
地址:国家:中国, 省:吉林, 市:长春
克隆之后:
员工2的信息:
姓名:西南交通大学, 年龄:114
地址:国家:中国, 省:四川, 市:成都
员工1的信息:
姓名:明日科技, 年龄:12
地址:国家:中国, 省:吉林, 市:长春

实现了深克隆

一个方法自然是重写clone方法,添加如order.items=(LineItems)items.clone()的语句,也就是人为地添加对引用对象的复制。这个方法的缺点是如果引用对象有很多,或者说引用套引用很多重,那么太麻烦了。业界常用的方法是使用串行化然后反串行化的方法来实现深克隆。由于串行化后,对象写到流中,所有引用的对象都包含进来了,所以反串行化后,对等于生成了一个完全克隆的对象。
这个方法的要求是对象(包括被引用对象)必须事先了Serializable接口,否则就要用transient关键字将其排除在复制过程中。

JAVA之路_假克隆、浅克隆、深克隆的更多相关文章

  1. java 浅克隆 深克隆

    对象的克隆是java的一项高级技术,他可以根据给定的对象,获得与其完全相同的另一个对象. 1.浅克隆主要是复制对象的值 2.深克隆:当类存在聚合关系的时候,克隆就必须考虑聚合对象的克隆,可以复制引用类 ...

  2. Java——对象的复制、克隆、序列化

    原创作者: https://blog.csdn.net/lmb55/article/details/78277878对象克隆(复制)假如说你想复制一个简单变量.很简单: int apples = 5; ...

  3. java 浅拷贝和深拷贝 对象克隆clone

    分一下几点讨论: 为什么要克隆? 如何实现克隆 浅克隆和深克隆 解决多层克隆问题 总结 一:为什么要克隆? 大家先思考一个问题,为什么需要克隆对象?直接new一个对象不行吗? 答案是:克隆的对象可能包 ...

  4. Java之路——敬JAVA初学者(作者:MoMo)

    作为一名大四的毕业生,大学三年过,有得有失.作为一个喜欢编程,喜欢JAVA的人,自学其实是一件美事,很有意思的事.要是能再找个女朋友一起学.嘿嘿,就不枉在大学走了一遭啊!    要离开学校了,还是想留 ...

  5. java画图程序_图片用字母画出来_源码发布_版本二

    在上一个版本:java画图程序_图片用字母画出来_源码发布 基础上,增加了图片同比例缩放,使得大像素图片可以很好地显示画在Notepad++中. 项目结构: 运行效果1: 原图:http://imag ...

  6. java画图程序_图片用字母画出来_源码发布

    在之前写了一篇blog:java画图程序_图片用字母画出来 主要是把一些调试的截图发布出来,现在程序调试我认为可以了(当然,你如果还想调试的话,也可以下载源码自己调试). 就把源码发布出来. 项目结构 ...

  7. java画图程序_图片用字母画出来

    最近在研究怎样将图片用字母在文本编辑工具中“画”出来. 你看了这个可能还不知道我想说什么? 我想直接上图,大家一定就知道了 第一张:小猫 原图:http://www.cnblogs.com/hongt ...

  8. Java之路——名词解释(一)

    一.开篇 许多人在初接触Java的时候,都会被各种Java的英文缩写名词给弄得头晕脑胀.看一个技术,内容里又会有一堆其他的技术名词,看了半天不知所云.尝试去查一下这些名词的解释,除了非常学术性的解释之 ...

  9. Java之路——环境配置与编译运行

    本文大纲 一.开篇 二.JDK下载 三.JDK安装 四.环境配置 五.初识Java编译 六.Java与Javac 七.第一个Java程序 八.总结 九.参考资料 一.开篇 通过对之前Java之路的了解 ...

随机推荐

  1. Taro 周报 #7: 收获「e代驾」案例,发布 v2.2.16 和 v3.2.0-canary.2

    Taro 周报 2020 年 12 月 05 日 - 2020 年 12 月 12 日 ,更多的Taro周报点击 Taro 大事件 58 技术发布文章<开源 | Taro 3 支持 React ...

  2. 如何使用iis发布多个ftp,为何ftp 503错误?

    使用iis做网站时,需要每个网站都是80端口,所以用到了域名,为了方便发布应用,故将所有网站均添加了ftp发布,当我添加ftp域名绑定后,发现根本无法登陆ftp服务器,后经过百度+博客发现,解决方案: ...

  3. Cassandra与Kafka的集成

    Cassandra和Kafka经常一起用于微服务架构中.本文将介绍几种Cassandra和Kafka常见的集成模式.   简介   如果您的开发团队乐于接纳微服务架构的优点,那么您就会了解到,Kafk ...

  4. 又一个小而美的Java 开发框架: Solon 1.2 新篇

    Solon 1.2 发布后,取消了X类名前缀.故对此文做些调整. Solon 是Java世界里一个新的极易上手的Java开发框架.参考过 Javalin . Spring boot 等很多现有框架的设 ...

  5. .netcore 微服务快速开发框架 Anno&Viper -分布式锁是个什么鬼

    1.什么是锁 锁是为了解决多线程或者多进程资源竞争的问题. 同一进程的多个线程资源竞争可以用lock解决. lock 关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区. 如果其他线 ...

  6. 数据接口请求异常:parsererror

    问题一:直接拿别人的文件放在本地打开 如下图 原因:这是提示"交叉源请求仅支持协议方案:HTTP.数据.Chrome.Chrome扩展.HTTPS." 也就是你不能用本地文件打开, ...

  7. eclipse中安装jetty插件并使用

    一.eclipse中jetty插件安装: 打开eclipse,依次点击菜单Help->Eclipse Marketplace,在Find后面的框中输入jetty,选择第一项进行install即可 ...

  8. 每日一个linux命令6 -- rmdir

    rmdir doc 如果doc为空目录则删除,否则无法删除. rmdir -p test2/test3 递归删除空目录,首先判断test3,如果test3为空,则删除test3,此时判断test2,如 ...

  9. java之volatile

    一.谈谈对volatile的理解 volatile是java虚拟机提供的轻量级的同步机制 保证可见性.不保证原子性.禁止指令重排 1.可见性理解:所有线程存放都是主内存的副本(比如某个变量值为25), ...

  10. tree 中文(转)

    原文:http://www.dutor.net/index.php/2009/05/tree-cn-code/ 简介: tree命令可以以目录树的形式显示指定(默认显示这个文件系统)目录的所有文件夹和 ...