一、克隆的原理与应用

clone在堆上分配内存,分配的内存和源对象(即调用clone方法的对象)相同,然后再使用原对象中对应的各个域,填充新对象的域, 填充完成之后,clone方法返回,一个新的相同的对象被创建,同样可以把这个新对象的引用发布到外部。如果,想要对该对象进行处理,又想保留原来数据进行接下来的操作,clone就很方便。

二、克隆的实现

1、被克隆的类必须自己实现Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。Cloneable 接口实际上是个标识接口,没有任何接口方法。

2、覆盖Object.clone()方法。

三、浅拷贝与深拷贝

浅拷贝:在填充新对象域的时候,进行简单的字段赋值。

深拷贝:按照惯例,此方法返回的对象应该独立于该对象(正被复制的对象)。要获得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段进行修改。这通常意味着要复制包含正在被复制对象的内部“深层结构”的所有可变对象,并使用对副本的引用替换对这些对象的引用。如果一个类只包含基本字段或对不变对象的引用,那么通常不需要修改 super.clone 返回的对象中的字段。(简单来说,就是将该对象内部的对象也克隆一份,而不是简单的引用赋值)

可变对象:对象创建后字段值可以改变)

浅拷贝:

class Head {
String s;
void set(String s1) {
s = s1;
}
}
public class Person implements Cloneable{ Head head;
Person(Head head) {
this.head = head;
}
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException{
Person p = new Person(new Head());
Person p1 = (Person)p.clone();
System.out.println("p == p1 " + (p == p1));
System.out.println("p.head == p1.head " + (p.head == p1.head));
} }

输出结果:

p == p1 false
p.head == p1.head true

结果分析:

可以从结果过中看到,克隆创建了一个新的Person对象,但是p.head与p1.head仍然指向同一对象,也就是说p与p1仍然存在联系,这是我们不想看到的。

深拷贝:

class Head implements Cloneable{
String s;
void set(String s1) {
s = s1;
}
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
public class Person implements Cloneable{ Head head;
Person(Head head) {
this.head = head;
}
protected Object clone() throws CloneNotSupportedException{
Person p = (Person)super.clone();
p.head = (Head)head.clone();
return p;
}
public static void main(String[] args) throws CloneNotSupportedException{
Person p = new Person(new Head());
Person p1 = (Person)p.clone();
System.out.println("p == p1 " + (p == p1));
System.out.println("p.head == p1.head " + (p.head == p1.head));
} }

输出结果:

p == p1 false
p.head == p1.head false

结果分析:要实现深层拷贝要将对象内部的对象拷贝。

好文推荐:详解Java中的clone方法

Clone()方法详解的更多相关文章

  1. 方法object面试题分析:7JAVA中Object的clone方法详解-克隆-深克隆

    时间紧张,先记一笔,后续优化与完善.     每日一道理 翻开早已发黄的页张,试着寻找过去所留下的点点滴滴的足迹.多年前的好友似乎现在看来已变得陌生,匆忙之间,让这维持了多年的友谊变淡,找不出什么亲切 ...

  2. 转:Java中的Clone()方法详解

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

  3. jquery之clone()方法详解

    clone()函数用于克隆当前匹配元素集合的一个副本,并以jQuery对象的形式返回.你也可以简单地理解为:克隆当前jQuery对象. 你还可以指定是否复制这些匹配元素(甚至它们的子元素)的附加数据( ...

  4. clone方法详解

    http://blog.csdn.net/zhangjg_blog/article/details/18369201/

  5. Clone使用方法详解【转载】

    博客引用地址:Clone使用方法详解 Clone使用方法详解   java“指针”       Java语言的一个优点就是取消了指针的概念,但也导致了许多程序员在编程中常常忽略了对象与引用的区别,本文 ...

  6. Android源码下载方法详解

    转自:http://www.cnblogs.com/anakin/archive/2011/12/20/2295276.html Android源码下载方法详解 相信很多下载过内核的人都对这个很熟悉 ...

  7. PHP 中 16 个魔术方法详解

    PHP 中 16 个魔术方法详解   前言 PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods),这些方法在PHP中充当了举足轻重的作用. 魔术方法包括: __constru ...

  8. session的使用方法详解

    session的使用方法详解 Session是什么呢?简单来说就是服务器给客户端的一个编号.当一台WWW服务器运行时,可能有若干个用户浏览正在运正在这台服务器上的网站.当每个用户首次与这台WWW服务器 ...

  9. Kooboo CMS - Html.FrontHtml[Helper.cs] 各个方法详解

    下面罗列了方法详解,每一个方法一篇文章. Kooboo CMS - @Html.FrontHtml().HtmlTitle() 详解 Kooboo CMS - Html.FrontHtml.Posit ...

随机推荐

  1. LA 6979 Known Notation 构造+贪心 铜牌题

    题意:给出一个字符串,有两种操作: 1.插入一个数字  2.交换两个字符   问最少多少步可以把该字符串变为一个后缀表达式(操作符只有*) #include <cstdio> #inclu ...

  2. CSP-S 模拟测试 51 题解

    考试过程: 惯例先看一遍三道题,T1 一开始反应要求割点,但是这是有向图,肯定不能求割点,康了一下数据范围,有40%是树的,还不错,决定待会在打. 看T2 字符串题,完了我字符串最弱了,肯定只能打暴力 ...

  3. Java 面试题 三 <JavaWeb应用调优线程池 JVM原理及调优>

    1.Java Web应用调优线程池 不论你是否关注,Java Web应用都或多或少的使用了线程池来处理请求.线程池的实现细节可能会被忽视,但是有关于线程池的使用和调优迟早是需要了解的.本文由浅入深,介 ...

  4. 栈的数组和链表实现(Java实现)

    我以前用JavaScript写过栈和队列,这里初学Java,于是想来实现栈,基于数组和链表. 下面上代码: import java.io.*; //用接口来存放需要的所有操作 interface st ...

  5. codeforces#1196F. K-th Path(最短路,思维题)

    题目链接: https://codeforces.com/contest/1196/problem/F 题意: 在无向图的所有最短路点对中,求出第$k$大 数据范围: $ 1 \leq k \leq ...

  6. 第十四周课程总结&实验报告(简单记事本的实现)

    1.JDBC概述 JDBC提供了一种与平台无关的用于执行SQL语句的标准JavaAPI,可以方便的实现多种关系型数据库的统一操作,它由一组用Java语言编写的类和接口组成 主要常用操作类与接口: ja ...

  7. linux系统及命令学习

    1,基本概念 Shell(命令行):是一个程序,接受键盘输入的命令,并将命令传递给操作系统进行执行. Bash:Bourne Again Shell, 是大多数linux系统分之中所带的一种shell ...

  8. 映射器Mapping

    1)  org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping(核心) 将程序员定义的Action所对应的<bean& ...

  9. 使用Jsp/Js/Ajax/Json/Jquery/Easyui + Servlet + JDBC + Lucene/Mysql/Oracle完成数据库分页

    package loaderman.action; import java.io.IOException; import java.io.PrintWriter; import java.util.L ...

  10. LinearLayout线性布局

    作用 : 线性布局会将容器中的组件一个一个排列起来, LinearLayout可以控制组件横向或者纵向排列, 通过android:orientation属性控制; 不换行属性 : 线性布局中的组件不会 ...