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对象不同
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.