失效链接处理 |
对象克隆(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
|