1.首先,你要知道怎么实现克隆:实现Cloneable接口,在bean里面重写clone()方法,权限为public。

2.其次,你要大概知道什么是地址传递,什么是值传递。

3.最后,你要知道你为什么使用这个clone方法。

先看第一条,简单的克隆代码的实现。这个也就是我们在没了解清楚这个Java的clone的时候,会出现的问题。

看完代码,我再说明这个时候的问题。

先看我要克隆的学生bean的代码:

package com.lxk.model;

/**

* 学生类:有2个属性:1,基本属性-String-name;2,引用类型-Car-car。

*

* Created by lxk on 2017/3/23

*/

public class Student implements Cloneable {

private String name;

private Car car;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Car getCar() {

return car;

}

public void setCar(Car car) {

this.car = car;

}

@Override

public String toString() {

return "Student{" +

"name='" + name + '\'' +

", car=" + car +

'}';

}

@Override

public Student clone() {

Student student = null;

try {

student = (Student) super.clone();

} catch (CloneNotSupportedException ignored) {

System.out.println(ignored.getMessage());

}

return student;

}

}

学生内部引用了Car这个bean

package com.lxk.model;

import java.util.List;

public class Car implements Comparable {

private String sign;

private int price;

private List myDog;

private List boys;

public Car() {

}

public Car(String sign, int price) {

this.sign = sign;

this.price = price;

}

public Car(String sign, int price, List myDog) {

this.sign = sign;

this.price = price;

this.myDog = myDog;

}

public Car(String sign, int price, List myDog, List boys) {

this.sign = sign;

this.price = price;

this.myDog = myDog;

this.boys = boys;

}

public String getSign() {

return sign;

}

public void setSign(String sign) {

this.sign = sign;

}

public int getPrice() {

return price;

}

public void setPrice(int price) {

this.price = price;

}

public List getMyDog() {

return myDog;

}

public void setMyDog(List myDog) {

this.myDog = myDog;

}

public List getBoys() {

return boys;

}

public void setBoys(List boys) {

this.boys = boys;

}

@Override

public int compareTo(Car o) {

//同理也可以根据sign属性排序,就不举例啦。

return this.getPrice() - o.getPrice();

}

@Override

public String toString() {

return "Car{" +

"sign='" + sign + '\'' +

", price=" + price +

", myDog=" + myDog +

", boys=" + boys +

'}';

}

}

最后就是main测试类

package com.lxk.findBugs;

import com.lxk.model.Car;

import com.lxk.model.Student;

/**

* 引用传递也就是地址传递需要注意的地方,引起的bug

*

* Created by lxk on 2017/3/23

*/

public class Bug2 {

public static void main(String[] args) {

Student student1 = new Student();

Car car = new Car("oooo", 100);

student1.setCar(car);

student1.setName("lxk");

//克隆完之后,student1和student2应该没关系的,修改student1不影响student2的值,但是完之后发现,你修改car的值,student2也受影响啦。

Student student2 = student1.clone();

System.out.println("学生2:" + student2);//先输出student2刚刚克隆完之后的值,然后在修改student1的相关引用类型的属性值(car)和基本属性值(name)

car.setSign("X5");

student1.setName("xxx");

System.out.println("学生2:" + student2);//再次输出看修改的结果

}

}

之后就该是执行的结果图了:

对上面执行结果的疑惑,以及解释说明:

我们可能觉得自己在bean里面实现clone接口,重写了这个clone方法,那么学生2是经由学生1clone,复制出来的,

那么学生1和学生2,应该是毫不相干的,各自是各自,然后,在修改学生1的时候,学生2是不会受影响的。

但是结果,不尽人意。从上图执行结果可以看出来,除了名字,这个属性是没有被学生1影响,关于car的sign属性已经

因为学生1的变化而变化,这不是我希望的结果。

可见,这个简单的克隆实现也仅仅是个“浅克隆”,也就是基本类型数据,他是会给你重新复制一份新的,但是引用类型的,

他就不会重新复制份新的。引用类型包括,上面的其他bean的引用,list集合,等一些引用类型。

那么怎么实现深克隆呢?

对上述代码稍作修改,如下:

学生bean的clone重写方法如下所示:

@Override

public Student clone() {

Student student = null;

try {

student = (Student) super.clone();

if (car != null) {

student.setCar(car.clone());

}

} catch (CloneNotSupportedException ignored) {

System.out.println(ignored.getMessage());

}

return student;

}

然后还要Car类实现cloneable接口,复写clone方法:

@Override

public Car clone() {

Car car = null;

try {

car = (Car) super.clone();

if (myDog != null) {

car.setMyDog(Lists.newArrayList(myDog));

}

if (boys != null) {

car.setBoys(Lists.newArrayList(boys));

}

} catch (CloneNotSupportedException ignored) {

System.out.println(ignored.getMessage());

}

return car;

}

主测试代码不动,这个时候的执行结果如下:

可以看到,这个时候,你再修改学生1的值,就不会影响到学生2的值,这才是真正的克隆,也就是所谓的深克隆。

怎么举一反三?

可以看到,这个例子里面的引用类型就一个Car类型的属性,但是实际开发中,除了这个引用其他bean类型的属性外,

可能还要list类型的属性值用的最多。那么要怎么深克隆呢,就像我在Car bean类里面做的那样,把所有的引用类型的属性,

都在clone一遍。那么你在最上层调用这个clone方法的时候,他就是真的深克隆啦。

我代码里面那么判断是为了避免空指针异常。当然,这个你也得注意咯。

注意 重写clone方法的时候,里面各个属性的null的判断哦。

最后,觉得写的好,还请点个赞,留个言啥的。觉得有问题的,提出来,我改,但是,请不要踩我的文章。

java如何实现克隆接口_java之实现clone接口的详解,克隆一个对象--对应有浅克隆和深克隆,概念结合代码深入理解...相关推荐

  1. java中 enum什么意思_Java中枚举Enum的使用详解

    在某些情况下,一个类的对象时有限且固定的,如季节类,它只有春夏秋冬4个对象这种实例有限且固定的类,在 Java 中被称为枚举类: 在 Java 中使用 enum 关键字来定义枚举类,其地位与 clas ...

  2. java uml类图教程_Java利器之UML类图详解

    原标题:Java利器之UML类图详解 (点击上方公众号,可快速关注) 来源:伯乐在线专栏作者- Code4Android 如需转载,发送「转载」二字查看说明 前言 UML(Unified Modeli ...

  3. java原生类型没有封装_Java基本数据类型与封装类型详解(int和Integer区别)

    Java基本数据类型与封装类型详解(int和Integer区别) 发布于 2020-4-19| 复制链接 摘记: int是java提供的8种原始数据类型之一.Java为每个原始类型提供了封装类,Int ...

  4. java 封装表单数据类型_Java基本数据类型与封装类型详解(int和Integer区别)

    int是java提供的8种原始数据类型之一. Java为每个原始类型提供了封装类,Integer是java为int提供的封装类(即Integer是一个java对象,而int只是一个基本数据类型).in ...

  5. java 获取oracle表结构_Java导出oracle表结构实例详解

    Java导出oracle表结构实例详解 发布于 2020-7-20| 复制链接 摘记:  Java导出oracle表结构实例详解最近用到的,因为plsql是收费的,不让用,找了很多方法终于发现了这个. ...

  6. java this关键字的使用_Java this 关键字的使用方法详解

    Java this 关键字的使用方法详解 构造方法中的this关键字 构造方法是一个类的对象在通过new关键字创建时自动调用的,在程序中不能向调用其他方法一样通过方法名(也就是类名)来调用.但如果一个 ...

  7. java case 多个值_Java switch多值匹配操作详解

    这篇文章主要介绍了Java switch多值匹配操作详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 我们都知道 switch 用来走流程分支,大 ...

  8. java工厂模式静态工厂_Java设计模式之静态工厂模式详解

    本文实例讲述了Java设计模式之静态工厂模式.分享给大家供大家参考,具体如下: 静态工厂模式(static factory)也叫简单工厂模式. 涉及到3个角色:工厂类角色,抽象产品类角色和具体产品类角 ...

  9. java 将网页表格导出_Java导出网页表格Excel过程详解

    将网页中的table数据,导出到excel表格,可以使用java POI实现. java poi是java中操作excel的工具,支持excel的导入与导出,一般有三种形式: 1.HSSFWorkbo ...

最新文章

  1. java openssl库,Java的OpenSSL
  2. Insertion Sort List
  3. pythonsuper用法_python super函数使用方法详解
  4. html引入jquery_jQuery介绍
  5. 资产支持证券(Asset-Backed Security)
  6. Druid 在spring中的配置
  7. Docker数据卷(Volume)
  8. 关于java的取整/和取余%
  9. linux内核源代码_如何从源代码构建和安装最新的Linux内核
  10. php镂空窗,木窗镂空的雕刻象征着什么?黑色在彝族人民心中有何寓意?陆川猪为何是著名“陆川三宝”之一?...
  11. ajax跨域获取数据后处理,简单实现ajax获取跨域数据
  12. nginx负载均衡文件服务器配置虚拟目录代理refer防盗链
  13. RFID 芯片是什么
  14. centos 部署.netcore 开发环境
  15. Linux基于升序链表的定时器
  16. python移动文件
  17. 自定义tooltip
  18. 按首字母排序(汉字、英文、数字)简单实现
  19. DirectX组件和安装在系统上驱动程序
  20. 【ACL2020】结果已出,录用论文抢先看!

热门文章

  1. webpack-loader(加载器)
  2. 如何实现Activiti的分支条件的自定义配置(转)
  3. ERROR ITMS-90206:Invalid Bundle. The bundle at ‘xx.app/xx/xx.framework' contan
  4. 默认权限umask、文件系统权限、特殊权限
  5. Uva 524 相邻素数全排列
  6. Windows下配置Git
  7. C#中的数组和C++中数组的区别
  8. 数组任意取三个数中乘积最大值
  9. 什么是java虚拟机?
  10. ASp.net常用服务