java拷贝--clone
大纲:
- java如何拷贝对象。
- 浅拷贝
- 深拷贝
一、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的更多相关文章
- Java基础——clone()方法浅析
一.clone的概念 clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象.那 ...
- 分析java中clone()方法 (转载+修改)
Java中的clone() 方法 java所有的类都是从java.lang.Object类继承而来的,而Object类提供下面的方法对对象进行复制. protected native Object c ...
- java中clone的深入理解
Java中Clone的概念大家应该都很熟悉了,它可以让我们很方便的“制造”出一个对象的副本来,下面来具体看看java中的Clone机制是如何工作的? 1. Clone和Copy 假 ...
- Java中clone方法的使用
什么是clone 在实际编程过程中,我们常常要遇到这种情况:有一个对象object1,在某一时刻object1中已经包含了一些有效值,此时可能会需要一个和object1完全相同新对象object2,并 ...
- Java的clone方法效率问题
在Java中,经常会需要新建一个对象,很多情况下,需要这个新建的对象和现有的某个对象保持属性一致. 那么,就有两种方式来实现这个对象的构造: ①通过新建一个对象,为这个对象的属性根据原有对象的属性来进 ...
- Java Object Clone
Java Object Clone User user = new User(); user.setName("tom"); User user1 = new User(); us ...
- Javascript对象拷贝(clone)
Javascript对象拷贝(clone),希望大家给点建议1. [代码]方法代码 function cp(source, target) { function isBaseType(v) { ...
- java拷贝字符文件
1.java拷贝字符文件 2.代码如下: package Demo1; import java.io.*; public class copyfile { public static void mai ...
- java 拷贝功能
java 中的 拷贝分为浅拷贝 和 深拷贝 浅拷贝需要实现Cloneable接口,深拷贝需要实现Serializable接口. public class Square implements Clone ...
随机推荐
- Mysql中(@i:=@i+1)的作用
Oracle中有一个伪列rownum,可以在生成查询结果表的时候生成一组递增的序列号.MySQL中没有这个伪列,但是有时候要用,可以用如下方法模拟生成一列自增序号. (1)sql示例:select ( ...
- shell script 二 判断符号【】 shift 偏移量 if then fi
判断符号[]类似于test.但是[]有通配符及正则表达式,为了区分,利用[]来做判断时,前后都需要加空格来区分.又一个坑 [ -z "$HOME" ];echo $? 例: 1 r ...
- dubbo-源码阅读之服务订阅
配置例子 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://w ...
- 【css对齐】块内或者行内图片与文字居中对齐最靠谱的方式!
块内或者行内图片与文字居中对齐最靠谱的方式! 做图片与文字在一行的按钮时候最常用到,总结了一个靠谱的方法,终于可以完美的对齐下面给个代码 首先是html: <p class="btnU ...
- python爬虫环境1
转载 https://cuiqingcai.com/5052.html 1.1 python3安装 配置环境变量:随后点击“新建”,新建一个条目,将刚才复制的C:\Python36复制进去.这里需要 ...
- windows线程函数必须为全局函数或者静态函数(转)
调用CreateThread(...)创建线程时要指定所创建线程的入口函数,此入口函数只能是全局函数或者类的静态成员函数. 全局函数很容易理解,但如果是类的成员函数则必须是静态成员函数,为何, 因为类 ...
- vue element-ui NavMenu错位问题
原因:子菜单全部打开后太长超过100% 解决方法:设置只能点击打开当前的菜单
- 简单API接口签名验证
前言 后端在写对外的API接口时,一般会对参数进行签名来保证接口的安全性,在设计签名算法的时候,主要考虑的是这几个问题: 1. 请求的来源是否合法 2. 请求参数是否被篡改 3. 请求的唯一性 我们的 ...
- python制作坦克对战
创建子弹类 import pygame class Bullet(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__i ...
- Java中的时间日期Date和Calendar
日期时间类 Date: Date类的构造方法: 可以发现Date类的toString方法被重写了. Date类的方法: SimpleDateFormat 它提供了解决Date输出问题的解决方案--格式 ...