Java知识分享网 - 轻松学习从此开始!    

Java知识分享网

Java1234官方群25:java1234官方群17
Java1234官方群25:838462530
        
SpringBoot+SpringSecurity+Vue+ElementPlus权限系统实战课程 震撼发布        

最新Java全栈就业实战课程(免费)

springcloud分布式电商秒杀实战课程

IDEA永久激活

66套java实战课程无套路领取

锋哥开始收Java学员啦!

Python学习路线图

锋哥开始收Java学员啦!
当前位置: 主页 > Java文档 > Java基础相关 >

对象克隆(clone)详解 PDF 下载


分享到:
时间:2020-05-12 21:13来源:http://www.java1234.com 作者:小锋  侵权举报
对象克隆(clone)详解 PDF 下载
失效链接处理
对象克隆(clone)详解 PDF 下载

下载地址:

提取码:u34s

相关截图:


主要内容:

Clone()方法详解 
一、克隆的原理与应用
clone在堆上分配内存,分配的内存和源对象(即调用clone方法的对象)相同,然后再使用原对象中对应的各个域,填充新对象的域, 填充完成之后,clone方法返回,一个新的相同的对象被创建,同样可以把这个新对象的引用发布到外部。如果,想要对该对象进行处理,又想保留原来数据进行接下来的操作,clone就很方便[1]。
二、克隆的实现
被克隆的类必须自己实现Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。Cloneable 接口实际上是个标识接口,没有任何方法和字段,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。这样做的目的是:创建并返回此对象的一个副本。对于任何对象x
表达式: x.clone() != x 的结果为:true
表达式: x.clone().getClass() == x.getClass() 的结果也为:true
但这些并非必须要满足的要求。
一般情况下: x.clone().equals(x)为 true,但这并非必须要满足的要求。
注意事项:
  1、而且按照惯例,实现此接口的类应该(使用公共方法)重写 Object.clone(它是受保护的)。
  如果不重写clone()方法好像不能用该方法克隆对象。
  2、如果在没有实现 Cloneable 接口的实例上调用 Object 的 clone 方法,则会导致抛出
  CloneNotSupportedException 异常。
三、浅克隆与深克隆
浅层克隆:在填充新对象域的时候,进行简单的字段赋值。
深层克隆:按照惯例,此方法返回的对象应该独立于该对象(正被复制的对象)。如果一个被克隆的对象的类中有非静态的其它类的对象的引用,要使被克隆的对象中这些内部的对象也有独立的对象,则有必要对这些内部对象的类增加clone()方法,以实现对被克隆对象内部的所有非静态对象的克隆,以使副本内部的引用指向新创建内部对象。如果一个类只包含基本字段或对静态对象的引用,那么通常不需要做深层的克隆。(简单来说,就是将该对象内部的对象也克隆一份,而不是简单的引用赋值)。
(可变对象(非静态对象):对象创建后字段值可以改变)
主类文件:
 CloneDemo.java
package clone;
import java.io.*;
public class CloneDemo {
   public static void main(String args[]) {
      TV changhong = new TV();
      changhong.setName("长虹电视");
      changhong.setPrice(5678);
      changhong.setSc(new Screen(19));
      try{
          TV kangjia = (TV) changhong.clone();
          kangjia.name="康佳d电视";
          kangjia.price=7888;
          kangjia.sc.setSize(21);
          System.out.println("changhong的名字:"+changhong.getName());
          System.out.println("changhong的价格:"+changhong.getPrice());
          System.out.println("changhong电视对象:"+changhong.getSc().toString());
          System.out.println("changhong的屏幕:"+changhong.getSc().size);
System.out.println();
          System.out.println("kangjia的名字:"+kangjia.getName());
          System.out.println("kangjia的价格:"+kangjia.getPrice());
          System.out.println("kangjia电视对象:"+kangjia.getSc().toString());
          System.out.println("kangjia的屏幕:"+kangjia.getSc().size);
      } catch (CloneNotSupportedException e) {
          e.printStackTrace();
      }
   }
}
 
浅层克隆:
tv.java
package clone;
import java.io.*;
public class TV implements Serializable, Cloneable {
   String name;
   int price;
   Screen sc;
 
   public TV clone() throws CloneNotSupportedException{
      TV tv = (TV) super.clone();
      return tv;
   }
   public Screen getSc() { return sc; }
   public void setSc(Screen sc) { this.sc = sc; }
   public void setName(String s) { name=s; }
   public void setPrice(int n) { price=n; }
   public String getName() { return name; }
   public int getPrice() { return price; }
}
 
class Screen implements Serializable, Cloneable {
   int size;
 
   Screen() {}
   Screen(int s) { size=s; }
   public int getSize() { return size; }
   public void setSize(int size) { this.size = size; }
}
输出结果:
changhong的名字:长虹电视
changhong的价格:5678
changhong电视对象:chapter10.例子13.Screen@4b67cf4d
changhong的屏幕:21
 
kangjia的名字:康佳d电视
kangjia的价格:7888
kangjia电视对象:chapter10.例子13.Screen@4b67cf4d
kangjia的屏幕:21
结果分析:
从结果过可以看出,通过TV对象changhong克隆(创建)了一个新的TV对象kangjia,但是kangjia内部的Screen对象sc与changhong的内部对象sc的地址是一样的,也就是说它们仍然指向同一对象,并没有完成内部对象克隆副本,而且你们看到我对kangjia对象的屏幕尺寸(21吋)的改变影响到了changhong对象的屏幕尺寸(changhong对象的屏幕原来尺寸是19,但是现在输出的尺寸却是21吋),这是我们不愿意看到的。如果想创建内部对象还需要调用Screen的构造方法来完成,那么对象的内部对象能否也被克隆呢?显然java是允许这做的,这就用到了我下面将要讲解的深层克隆方法。
 
深层克隆:
tv.java
package clone;
import java.io.*;
public class TV implements Serializable, Cloneable {
   String name;
   int price;
   Screen sc;
 
   public TV clone() throws CloneNotSupportedException{
      TV tv = (TV) super.clone();
      tv.sc=sc.clone();//调用内部对象的类重写的clone()方法克隆内部对象
      return tv;
   }
   public Screen getSc() { return sc; }
   public void setSc(Screen sc) { this.sc = sc; }
   public void setName(String s) { name=s; }
   public void setPrice(int n) { price=n; }
   public String getName() { return name; }
   public int getPrice() { return price; }
}
 
class Screen implements Serializable, Cloneable {
   int size;
 
   Screen() {}
   Screen(int s) { size=s; }
   public int getSize() { return size; }
   public void setSize(int size) { this.size = size; }
//重写clone()方法完成对象克隆
   public Screen clone() throws CloneNotSupportedException {
      Screen sc = (Screen) super.clone();
      return sc;
   }
}
 
输出结果:
changhong的名字:长虹电视
changhong的价格:5678
changhong电视对象:chapter10.例子13.Screen@4b67cf4d
changhong的屏幕:19
 
kangjia的名字:康佳d电视
kangjia的价格:7888
kangjia电视对象:chapter10.例子13.Screen@15aeb7ab
kangjia的屏幕:21
结果分析:
从结果可以看出,通过TV对象changhong克隆(创建)了一个新的TV对象kangjia,kangjia内部的Screen对象sc与changhong的内部对象sc的地址不一样的,也就是说它们指向不同的对象,完成了内部对象克隆副本的需求,而且你们看到我们对kangjia对象的屏幕尺寸(21吋)的改变并没有影响到changhong对象的屏幕尺寸(19吋)。
 
参考文献
[1]卑微芒果. 博客园[w]. https://www.cnblogs.com/mgblogs/p/11519125.html

 

------分隔线----------------------------

锋哥公众号


锋哥微信


关注公众号
【Java资料站】
回复 666
获取 
66套java
从菜鸡到大神
项目实战课程

锋哥推荐