Cloneable和Serializable一樣都是標記型接口,它們內部都沒有方法和屬性,implements Cloneable表示該對象能被克隆,能使用Object.clone()方法。如果沒有implements Cloneable的類調用Object.clone()方法就會拋出CloneNotSupportedException。
克隆的理解
一、Cloneable 的用途
Cloneable和Serializable一樣都是標記型接口,它們內部都沒有方法和屬性,implements Cloneable表示該對象能被克隆,能使用Object.clone()方法。如果沒有implements Cloneable的類調用Object.clone()方法就會拋出CloneNotSupportedException。
Cloneable和Serializable一樣都是標記型接口,它們內部都沒有方法和屬性,implements Cloneable表示該對象能被克隆,能使用Object.clone()方法。如果沒有implements Cloneable的類調用Object.clone()方法就會拋出CloneNotSupportedException。
二、克隆的分類
1、淺克隆(shallow
clone)
拷貝對象的時候僅僅拷貝對象本身和對象中的基本變量,而不拷貝對象中包含的引用所指向的對象。
2、深克隆(deep
clone)
拷貝對象的時候不僅僅拷貝對象本身,同時拷貝對象所包含的的引用所指向的對象。
舉例說明:
對象A1中包含對B1的引用,B1中包含對C1的引用。
淺拷貝A1得到A2,A2中依然包含對B1的引用,B1中依然包含對C1的引用。深拷貝則是對淺拷貝的遞歸,深拷貝A1得到A2,A2中包含對B2(B1的copy)的引用,B2中包含對C2(C1的copy)的引用。
三、克隆的舉例
要讓一個對象進行克隆,其實就是兩個步驟:
1、讓類實現java.lang.Cloneable接口
2、重寫(override) Object類的clone()方法
代碼實現:
package com.tyxh.create;
public class Wife implements Cloneable
{
private int id;
private String name;
public int getId()
{
return id;
}
public void setId( int id)
{
this. id =
id;
}
public String getName() {
return name;
}
public void setName(String
name) {
this. name =
name;
}
public Wife( int id,String
name) {
this. id =
id;
this. name =
name;
}
@Override
public int hashCode()
{
final int prime
= 31;
int result = 1;
result = prime * result + id;
result = prime * result + (( name == null)
? 0 : name.hashCode());
return result;
}
@Override
public boolean equals (Object
obj) {
if ( this ==
obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Wife other = (Wife) obj;
if ( id !=
other. id)
return false;
if ( name == null)
{
if (other. name != null)
return false;
} else if (! name.equals(other. name))
return false;
return true;
}
@Override
public Object clone() throws CloneNotSupportedException
{
return super.clone();
}
public static void main(String[]
args) throws CloneNotSupportedException {
Wife wife = new Wife(1, "wang");
Wife wife2 = null;
wife2 = (Wife) wife.clone();
System. out.println( "wife
: " + wife);
System. out.println( "wife2
: " + wife2);
wife.setName( "tyxh");
System. out.println( "wife
: " + wife);
System. out.println( "wife2
: " + wife2);
wife2.setName( "sotaof");
System. out.println( "wife
: " + wife);
System. out.println( "wife2
: " + wife2);
//上面兩個輸出的地址相同,克隆的只是引用
System. out.println( "class
same="+(wife.getClass()==wife2.getClass())); //true
System. out.println( "object
same="+(wife==wife2));//false 說明兩個對象的地址不同
System. out.println( "object
equals="+(wife.equals (wife2)));//false
}
}
輸入結果:
wife : com.tyxh.create.Wife@3795e3
wife2 : com.tyxh.create.Wife@3795e3
wife : com.tyxh.create.Wife@369415
wife2 : com.tyxh.create.Wife@3795e3
wife : com.tyxh.create.Wife@369415
wife2 : com.tyxh.create.Wife@ca8fb940
class same=true
object same=false
object equals=false
第一行和第二行相同的原因不是因爲克隆後的wife和wife2地址相同,而是因爲hashcode的緣故,我們注意hashcode的返回值result = prime * result + (( name == null)
? 0 : name.hashCode());name變化的話,返回值就會發生改變。如果你在hashcode方法中返回1,那麼結果就會是@1;
當對wife的name值進行修改之後,wife的值變化了,而wife2的值沒有變化;
當對wife2的name值進行修改之後,wife2的值變化了,而wife的值沒有變化。
但是這並不代表wife和wife2的地址發生了改變,這僅僅能說明wife和wife2的值發生了改變。當我們註釋掉hashCode()和equals()方法之後,再看一下輸出結果:
wife : com.tyxh.create.Wife@3771ed5e
wife2 : com.tyxh.create.Wife@1896d2c2
wife : com.tyxh.create.Wife@3771ed5e
wife2 : com.tyxh.create.Wife@1896d2c2
wife : com.tyxh.create.Wife@3771ed5e
wife2 : com.tyxh.create.Wife@1896d2c2
class same=true
object same=false
object equals=false
通過結果可以看出,不管是對wife還是對wife2進行值的修改,它們的地址都沒有改變。
四.淺克隆的舉例
package com.tyxh.create;
public class Husband implements Cloneable
{
private int id;
private Wife wife;
public Wife getWife() {
return wife;
}
public void setWife(Wife
wife) {
this. wife =
wife;
}
public int getId()
{
return id;
}
public void setId( int id)
{
this. id =
id;
}
public Husband( int id)
{
this. id =
id;
}
@Override
public int hashCode()
{
final int prime
= 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
protected Object clone() throws CloneNotSupportedException
{
return super.clone();
}
@Override
public boolean equals(Object
obj) {
if ( this ==
obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Husband other = (Husband) obj;
if ( id !=
other. id)
return false;
return true;
}
/**
* @param args
* @throws CloneNotSupportedException
*/
public static void main(String[]
args) throws CloneNotSupportedException {
Wife wife = new Wife(1, "jin");
Husband husband = new Husband(1);
Husband husband2 = null;
husband.setWife(wife);
husband2 = (Husband) husband.clone();
System. out.println( "husband
: " + husband);
System. out.println( "husband2
: " + husband2);
System. out.println( "husband
class same="+(husband.getClass()==husband2.getClass())); //true
System. out.println( "husband
object same="+(husband==husband2));//false
System. out.println( "husband
object equals="+(husband.equals(husband)));//true
System. out.println( "wife
class same="+(husband.getWife().getClass()==husband2.getWife().getClass())); //true
System. out.println( "wife
object same="+(husband.getWife()==husband2.getWife())); //true 說明引用是同一個引用
System. out.println( "wife
object equals="+(husband.getWife().equals(husband.getWife()))); //true
}
}
輸入結果如下:
husband : com.tyxh.create.Husband@20
husband2 : com.tyxh.create.Husband@20
husband class same=true
husband object same=false
husband object equals=true
wife class same=true
wife object same=true
wife object equals=true
四.深克隆的舉例
package com.tyxh.create;
public class Husband implements Cloneable
{
private int id;
private Wife wife;
public Wife getWife() {
return wife;
}
public void setWife(Wife
wife) {
this. wife =
wife;
}
public int getId()
{
return id;
}
public void setId( int id)
{
this. id =
id;
}
public Husband( int id)
{
this. id =
id;
}
@Override
public int hashCode()
{ //myeclipse 自動生成的
final int prime
= 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
protected Object clone() throws CloneNotSupportedException
{
Husband husband = (Husband) super.clone();
husband. wife = (Wife) husband.getWife().clone();
return husband;
}
@Override
public boolean equals(Object
obj) { //myeclipse 自動生成的
if ( this ==
obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Husband other = (Husband) obj;
if ( id !=
other. id)
return false;
return true;
}
/**
* @param args
* @throws CloneNotSupportedException
*/
public static void main(String[]
args) throws CloneNotSupportedException {
Wife wife = new Wife(1, "jin");
Husband husband = new Husband(1);
Husband husband2 = null;
husband.setWife(wife);
husband2 = (Husband) husband.clone();
System. out.println( "husband
: " + husband);
System. out.println( "husband2
: " + husband2);
System. out.println( "husband
class same="+(husband.getClass()==husband2.getClass())); //true
System. out.println( "husband
object same="+(husband==husband2));//false
System. out.println( "husband
object equals="+(husband.equals(husband)));//true
System. out.println( "wife
class same="+(husband.getWife().getClass()==husband2.getWife().getClass())); //true
System. out.println( "wife
object same="+(husband.getWife()==husband2.getWife())); //false 說明引用不是同一個引用
System. out.println( "wife
object equals="+(husband.getWife().equals(husband.getWife()))); //true
}
}
輸出結果如下:
husband : com.tyxh.create.Husband@20
husband2 : com.tyxh.create.Husband@20
husband class same=true
husband object same=false
husband object equals=true
wife class same=true
wife object same=false
wife object equals=true
五、通過反序列化克隆 (也是深克隆)
package com.tyxh.create;
import java.io.*;
public class BeanUtil
{
@SuppressWarnings( "unchecked")
public static <T>
T cloneTo(T src) {
ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();
ObjectOutputStream out = null;
ObjectInputStream in = null;
T dist = null;
try {
out = new ObjectOutputStream(memoryBuffer);
out.writeObject(src);
out.flush();
in = new ObjectInputStream( new ByteArrayInputStream(memoryBuffer.toByteArray()));
dist = (T) in.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(out != null)
{
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(in != null)
{
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return dist;
}
public static void main(String[]
args) {
Husband husband = new Husband(1);
Wife wife = new Wife(1, "jin");
husband.setWife(wife);
Husband husband2 = cloneTo(husband);
System. out.println("husband
class same="+(husband.getClass()==husband2.getClass())); //true
System. out.println( "husband
object same="+(husband==husband2));//false
System. out.println("husband
object equals="+(husband.equals(husband)));//true
System. out.println("wife
class same="+(husband.getWife().getClass()==husband2.getWife().getClass())); //true
System. out.println("wife
object same="+(husband.getWife()==husband2.getWife())); //false 說明引用不是同一個引用
System. out.println("wife
object equals="+(husband.getWife().equals(husband.getWife()))); //true
}
}
輸出結果如下:
husband class same=true
husband object same=false
husband object equals=true
wife class same=true
wife object same=false
wife object equals=true
通過第二行可以看出,反序列化之後的husband2與husband不是同一個對象
通過第五行可以看出,反序列化屬於一種深克隆,因爲husband和husband2的wife對象不同
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.