大纲:

  1. java如何拷贝对象。
  2. 浅拷贝
  3. 深拷贝

一、java如何拷贝对象

Person p = new Person();
Person p2 = p;

上例并不是一个拷贝操作,只是把p对象的引用赋给了p2,2个变量指向了同一片heap地址。

想实现拷贝操作需要做2件事情:

(1)实现Cloneable接口,这是一个空接口不用重写任何方法。

public interface Cloneable {}

(2)重写clone方法,注意clone方法是Object类中的native方法,并不是Cloneable接口的。

二、浅拷贝

改写Person类

@Data
public class Person implements Cloneable {
private String name;
private int age;
private Date birth; @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", birth=" + birth.getTime() +
'}';
} @Override
public Person clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {}
return (Person)clone;
}
}

调用clone方法复制对象:

Person p1 = new Person();
Person p2 = p1.clone();

这样p1,p2就不是一个对象了。

三、深拷贝

以上Person对象中的成员变量都是java原生对象和基础数据类型,浅拷贝足以使Person拥有拷贝的功能。

如果为Person加上一个自定类的成员变量

@Data
public class Father {
private String name;
private int age; @Override
public String toString() {
return "Father{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Person implements Cloneable {
private String name;
private int age;
private Date birth;
private Father father;
}

这样做后person中的father对象无法实现拷贝

测试例:

public static void main(String[] args){
Person p1 = new Person();
p1.setName("p1");
Father f1 = new Father();
f1.setName("f1");
p1.setFather(f1);
Person p2 = (Person) p1.clone();
p2.getFather().setName("f2");
p2.setName("p2");
System.out.println(p1);
System.out.println(p2); //结果
//Person{name='p1', age=0, birth=null, father=Father{name='f2', age=0}}
//Person{name='p2', age=0, birth=null, father=Father{name='f2', age=0}}
}

可以看到person对象实现了拷贝,但是father对象还是引用了同一个对象。

深拷贝实现步骤:

(1)使自定义的类的成员变量实现Cloneable接口并重写clone方法。

@Data
public class Father implements Cloneable{
private String name;
private int age; @Override
public String toString() {
return "Father{" +
"name='" + name + '\'' +
", age=" + age +
'}';
} @Override
public Father clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {}
return (Father) clone;
}
}

(2)成员变量重写clone方法后,还需要将成员变量的拷贝对象显式赋值。

@Data
public class Person implements Cloneable {
private String name;
private int age;
private Date birth;
private Father father; @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", birth=" + birth +
", father=" + father +
'}';
} @Override
public Person clone() {
Person clone = null;
try {
clone = (Person) super.clone();
} catch (CloneNotSupportedException e) {}
//这里显式赋值
if(father!=null){
clone.setFather(father.clone());
}
return clone;
}
}

至此person中的father变量也完成了拷贝,可用上面的测试例子验证一下。

public static void main(String[] args){
Person p1 = new Person();
p1.setName("p1");
Father f1 = new Father();
f1.setName("f1");
p1.setFather(f1);
Person p2 = (Person) p1.clone();
p2.getFather().setName("f2");
p2.setName("p2");
System.out.println(p1);
System.out.println(p2);
//结果
//Person{name='p1', age=0, birth=null, father=Father{name='f1', age=0}}
//Person{name='p2', age=0, birth=null, father=Father{name='f2', age=0}}
}

java拷贝--clone的更多相关文章

  1. Java基础——clone()方法浅析

    一.clone的概念 clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象.那 ...

  2. 分析java中clone()方法 (转载+修改)

    Java中的clone() 方法 java所有的类都是从java.lang.Object类继承而来的,而Object类提供下面的方法对对象进行复制. protected native Object c ...

  3. java中clone的深入理解

    Java中Clone的概念大家应该都很熟悉了,它可以让我们很方便的“制造”出一个对象的副本来,下面来具体看看java中的Clone机制是如何工作的?      1. Clone和Copy      假 ...

  4. Java中clone方法的使用

    什么是clone 在实际编程过程中,我们常常要遇到这种情况:有一个对象object1,在某一时刻object1中已经包含了一些有效值,此时可能会需要一个和object1完全相同新对象object2,并 ...

  5. Java的clone方法效率问题

    在Java中,经常会需要新建一个对象,很多情况下,需要这个新建的对象和现有的某个对象保持属性一致. 那么,就有两种方式来实现这个对象的构造: ①通过新建一个对象,为这个对象的属性根据原有对象的属性来进 ...

  6. Java Object Clone

    Java Object Clone User user = new User(); user.setName("tom"); User user1 = new User(); us ...

  7. Javascript对象拷贝(clone)

    Javascript对象拷贝(clone),希望大家给点建议​1. [代码]方法代码 function cp(source, target) {    function isBaseType(v) { ...

  8. java拷贝字符文件

    1.java拷贝字符文件 2.代码如下: package Demo1; import java.io.*; public class copyfile { public static void mai ...

  9. java 拷贝功能

    java 中的 拷贝分为浅拷贝 和 深拷贝 浅拷贝需要实现Cloneable接口,深拷贝需要实现Serializable接口. public class Square implements Clone ...

随机推荐

  1. Mysql中(@i:=@i+1)的作用

    Oracle中有一个伪列rownum,可以在生成查询结果表的时候生成一组递增的序列号.MySQL中没有这个伪列,但是有时候要用,可以用如下方法模拟生成一列自增序号. (1)sql示例:select ( ...

  2. shell script 二 判断符号【】 shift 偏移量 if then fi

    判断符号[]类似于test.但是[]有通配符及正则表达式,为了区分,利用[]来做判断时,前后都需要加空格来区分.又一个坑 [ -z "$HOME" ];echo $? 例: 1 r ...

  3. dubbo-源码阅读之服务订阅

    配置例子 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://w ...

  4. 【css对齐】块内或者行内图片与文字居中对齐最靠谱的方式!

    块内或者行内图片与文字居中对齐最靠谱的方式! 做图片与文字在一行的按钮时候最常用到,总结了一个靠谱的方法,终于可以完美的对齐下面给个代码 首先是html: <p class="btnU ...

  5. python爬虫环境1

    转载 https://cuiqingcai.com/5052.html 1.1 python3安装  配置环境变量:随后点击“新建”,新建一个条目,将刚才复制的C:\Python36复制进去.这里需要 ...

  6. windows线程函数必须为全局函数或者静态函数(转)

    调用CreateThread(...)创建线程时要指定所创建线程的入口函数,此入口函数只能是全局函数或者类的静态成员函数. 全局函数很容易理解,但如果是类的成员函数则必须是静态成员函数,为何, 因为类 ...

  7. vue element-ui NavMenu错位问题

    原因:子菜单全部打开后太长超过100% 解决方法:设置只能点击打开当前的菜单

  8. 简单API接口签名验证

    前言 后端在写对外的API接口时,一般会对参数进行签名来保证接口的安全性,在设计签名算法的时候,主要考虑的是这几个问题: 1. 请求的来源是否合法 2. 请求参数是否被篡改 3. 请求的唯一性 我们的 ...

  9. python制作坦克对战

    创建子弹类 import pygame class Bullet(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__i ...

  10. Java中的时间日期Date和Calendar

    日期时间类 Date: Date类的构造方法: 可以发现Date类的toString方法被重写了. Date类的方法: SimpleDateFormat 它提供了解决Date输出问题的解决方案--格式 ...