Java对象的浅度clone和深度clone_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Java对象的浅度clone和深度clone

Java对象的浅度clone和深度clone

 2013/8/25 18:55:09  beijishiqidu  程序员俱乐部  我要评论(0)
  • 摘要:最近在研究Java的深度拷贝,浏览了很多网友的博客,发现一个共同点,就是csdn,博客园,iteye上的文章都是如出一辙,互相拷贝,借鉴我就不说了,你发个错的在上面,这就是你的不对了,你发上去不就是让人看的么?这样做岂不是误人子弟?所以现在小弟决定自己写个小记,虽然内容不多,但是容易懂,代码都是经过我自己编码运行的,没有问题。好了,废话不多说了,开始正文吧1.浅度拷贝和深度拷贝概念⑴浅度拷贝(浅克隆)被拷贝对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象
  • 标签:Java

?

最近在研究Java的深度拷贝,浏览了很多网友的博客,发现一个共同点,就是csdn,博客园,iteye上的文章都是如出一辙,互相拷贝,借鉴我就不说了,你发个错的在上面,这就是你的不对了,你发上去不就是让人看的么?这样做岂不是误人子弟?所以现在小弟决定自己写个小记,虽然内容不多,但是容易懂,代码都是经过我自己编码运行的,没有问题。好了,废话不多说了,开始正文吧

?

1.浅度拷贝和深度拷贝概念

⑴浅度拷贝(浅克隆)

被拷贝对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。也就是说浅度拷贝仅仅拷贝所引用的对象,而不拷贝它所引用的对象,这个我在下面的例子中,大家可以看出来。

?

⑵深复制拷贝(深克隆)

被拷贝对象的所有变量都含有与原来的对象相同的值,那些引用其他对象的变量将指向被拷贝过的新对象,而不再是原有的那些被引用的对象,也就是说深度拷贝把要拷贝的对象所有引用的对象都拷贝了一遍,下面的例子也会体现出来。

?

2.Java的clone()方法

⑴clone方法将对象拷贝了一份并返回给调用者。一般而言,clone()方法满足:

①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象

②对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样

③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。

?

⑵Java中对象的克隆

①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。?

②在派生类中覆盖基类的clone()方法,并声明为public。?

③在派生类的clone()方法中,调用super.clone()。?

④在派生类中实现Cloneable接口

?

?

下面看个例子:(深度拷贝一般属性)

class Student implements Cloneable {

?

private String name;// 一般属性。

private int age;// 一般属性。

?

Student(String name, int age) {

this.name = name;

this.age = age;

}

?

public Object clone() {

Student o = null;

?

try {

o = (Student) super.clone();

} catch (CloneNotSupportedException e) {

System.out.println(e.toString());

}

return o;

}

?

public String getName() {

return name;

}

?

public void setName(String name) {

this.name = name;

}

?

public int getAge() {

return age;

}

?

public void setAge(int age) {

this.age = age;

}

?

}

?

public class TEST {

?

public static void main(String[] args) {

?

Student s1 = new Student("old", 18);

?

Student s2 = (Student) s1.clone();

?

System.out.println("对象中的一般属性");

?

System.out.println("修改之前");

System.out.println("name=" + s1.getName() + "," + "age=" + s1.getAge());

System.out.println("name=" + s2.getName() + "," + "age=" + s2.getAge());

?

s2.setName("new");

s2.setAge(23);

?

System.out.println("修改之后");

System.out.println("name=" + s1.getName() + "," + "age=" + s1.getAge());

System.out.println("name=" + s2.getName() + "," + "age=" + s2.getAge());

?

}

}

?

?

打印的结果:

?

对象中的一般属性

修改之前

name=old,age=18

name=old,age=18

修改之后

name=old,age=18

name=new,age=23

?

又一个例子(深度拷贝一般属性,浅度拷贝引用属性private Professor p;中的p是引用一个对象,

即使深度拷贝了Student中的属性,但是他这个属性依然是引用的拷贝,而这个引用却是指向同一个

对象,下面子的例子可以看出结果)

class Professor {

?

private String name;

private int age;

?

Professor(String name, int age) {

this.name = name;

this.age = age;

}

?

public String getName() {

return name;

}

?

public void setName(String name) {

this.name = name;

}

?

public int getAge() {

return age;

}

?

public void setAge(int age) {

this.age = age;

}

}

?

class Student implements Cloneable {

?

private String name;// 一般属性。

private int age;// 一般属性。

private Professor p;

?

Student(String name, int age, Professor p) {

this.name = name;

this.age = age;

this.p = p;

}

?

public Object clone() {

Student o = null;

?

try {

o = (Student) super.clone();

} catch (CloneNotSupportedException e) {

System.out.println(e.toString());

}

return o;

}

?

public String getName() {

return name;

}

?

public void setName(String name) {

this.name = name;

}

?

public int getAge() {

return age;

}

?

public void setAge(int age) {

this.age = age;

}

?

public Professor getP() {

return p;

}

?

public void setP(Professor p) {

this.p = p;

}

?

}

?

public class TEST {

?

public static void main(String[] args) {

?

Professor p = new Professor("老虎", 50);

Student s1 = new Student("old", 18, p);

?

Student s2 = (Student) s1.clone();

?

System.out.println("看对象中的一般属性");

System.out.println("-------修改之前-------");

System.out.println("name=" + s1.getName() + "," + "age=" + s1.getAge());

System.out.println("name=" + s2.getName() + "," + "age=" + s2.getAge());

?

s2.setName("new");

s2.setAge(23);

?

System.out.println("----=--修改之后-------");

System.out.println("name=" + s1.getName() + "," + "age=" + s1.getAge());

System.out.println("name=" + s2.getName() + "," + "age=" + s2.getAge());

?

System.out.println("==================================");

System.out.println("看对象中的引用属性");

?

System.out.println("-------修改之前------");

System.out.println("叫兽的name=" + s1.getP().getName());

System.out.println("叫兽的name=" + s2.getP().getName());

?

s2.getP().setName("hahahaha");

?

System.out.println("-------修改之后-----");

System.out.println("叫兽的name=" + s1.getP().getName());

System.out.println("叫兽的name=" + s2.getP().getName());

?

}

}

?

?

打印的结果:

?

看对象中的一般属性

-------修改之前-------

name=old,age=18

name=old,age=18

----=--修改之后-------

name=old,age=18

name=new,age=23

==================================

看对象中的引用属性

-------修改之前------

叫兽的name=老虎

叫兽的name=老虎

-------修改之后-----

叫兽的name=hahahaha

叫兽的name=hahahaha

?

又一个例子(深度拷贝一般属性,深度拷贝引用属性private Professor p;这个时候需要在Student中

的clone对象中去调用Professor的克隆方法,此时Professor需要实现Cloneable)

class Professor implements Cloneable{

?

private String name;

private int age;

?

Professor(String name, int age) {

this.name = name;

this.age = age;

}

?

public String getName() {

return name;

}

?

public void setName(String name) {

this.name = name;

}

?

public int getAge() {

return age;

}

?

public void setAge(int age) {

this.age = age;

}

?

@Override

protected Object clone() throws CloneNotSupportedException {

// TODO Auto-generated method stub

return super.clone();

}

}

?

class Student implements Cloneable {

?

private String name;// 一般属性。

private int age;// 一般属性。

private Professor p;

?

Student(String name, int age, Professor p) {

this.name = name;

this.age = age;

this.p = p;

}

?

public Object clone() {

Student o = null;

?

try {

o = (Student) super.clone();

} catch (CloneNotSupportedException e) {

System.out.println(e.toString());

}

try {

o.p = (Professor) o.p.clone();

} catch (CloneNotSupportedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return o;

}

?

public String getName() {

return name;

}

?

public void setName(String name) {

this.name = name;

}

?

public int getAge() {

return age;

}

?

public void setAge(int age) {

this.age = age;

}

?

public Professor getP() {

return p;

}

?

public void setP(Professor p) {

this.p = p;

}

?

}

?

public class TEST {

?

public static void main(String[] args) {

?

Professor p = new Professor("老虎", 50);

Student s1 = new Student("old", 18, p);

?

Student s2 = (Student) s1.clone();

?

System.out.println("看对象中的一般属性");

System.out.println("-------修改之前-------");

System.out.println("name=" + s1.getName() + "," + "age=" + s1.getAge());

System.out.println("name=" + s2.getName() + "," + "age=" + s2.getAge());

?

s2.setName("new");

s2.setAge(23);

?

System.out.println("----=--修改之后-------");

System.out.println("name=" + s1.getName() + "," + "age=" + s1.getAge());

System.out.println("name=" + s2.getName() + "," + "age=" + s2.getAge());

?

System.out.println("==================================");

System.out.println("看对象中的引用属性");

?

System.out.println("-------修改之前------");

System.out.println("叫兽的name=" + s1.getP().getName());

System.out.println("叫兽的name=" + s2.getP().getName());

?

s2.getP().setName("hahahaha");

?

System.out.println("-------修改之后-----");

System.out.println("叫兽的name=" + s1.getP().getName());

System.out.println("叫兽的name=" + s2.getP().getName());

?

}

}

?

打印的结果:

?

看对象中的一般属性

-------修改之前-------

name=old,age=18

name=old,age=18

----=--修改之后-------

name=old,age=18

name=new,age=23

==================================

看对象中的引用属性

-------修改之前------

叫兽的name=老虎

叫兽的name=老虎

-------修改之后-----

叫兽的name=老虎

叫兽的name=hahahaha

?

最后一个例子(用流的方式实现深度拷贝,很简单,不详细说明了,不过要注意要流化对象,

必须要实现Serializable接口)

class Professor implements Cloneable, Serializable {

?

/**

*?

*/

private static final long serialVersionUID = -9034223179100535667L;

private String name;

private int age;

?

Professor(String name, int age) {

this.name = name;

this.age = age;

}

?

public String getName() {

return name;

}

?

public void setName(String name) {

this.name = name;

}

?

public int getAge() {

return age;

}

?

public void setAge(int age) {

this.age = age;

}

?

protected Object clone() throws CloneNotSupportedException {

// TODO Auto-generated method stub

return super.clone();

}

?

public Object deepClone(Object o) {

?

Object obj = null;

?

// 将对象写到流里

ByteArrayOutputStream bo = new ByteArrayOutputStream();

ObjectOutputStream oo = null;

?

// 从流里读出来

ObjectInputStream oi = null;

ByteArrayInputStream bi = null;

try {

oo = new ObjectOutputStream(bo);

oo.writeObject(o);

?

oo.flush();

oo.close();

bi = new ByteArrayInputStream(bo.toByteArray());

oi = new ObjectInputStream(bi);

obj = oi.readObject();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} finally {

try {

// oi.close();

// oo.close();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

?

}

?

return obj;

}

?

}

?

class Student implements Cloneable {

?

private String name;// 常量对象。

private int age;

private Professor p;

?

Student(String name, int age, Professor p) {

this.name = name;

this.age = age;

this.p = p;

}

?

public Object clone() {

Student o = null;

?

try {

o = (Student) super.clone();

} catch (CloneNotSupportedException e) {

System.out.println(e.toString());

}

o.p = (Professor) o.getP().deepClone(p);

return o;

}

?

/**

* @return the name

*/

public String getName() {

return name;

}

?

/**

* @param name

* ? ? ? ? ? ?the name to set

*/

public void setName(String name) {

this.name = name;

}

?

/**

* @return the age

*/

public int getAge() {

return age;

}

?

/**

* @param age

* ? ? ? ? ? ?the age to set

*/

public void setAge(int age) {

this.age = age;

}

?

/**

* @return the p

*/

public Professor getP() {

return p;

}

?

/**

* @param p

* ? ? ? ? ? ?the p to set

*/

public void setP(Professor p) {

this.p = p;

}

?

}

?

public class TEST04 {

?

public static void main(String[] args) {

?

Professor p = new Professor("old", 50);

?

Student s1 = new Student("old", 18, p);

?

Student s2 = (Student) s1.clone();

?

Professor objP = (Professor) p.deepClone(p);

?

System.out.println("修改之前");

System.out.println("name=" + p.getName() + ", age =" + p.getAge());

System.out.println("name=" + objP.getName() + ", age =" + objP.getAge());

?

p.setName("hahaha");

objP.setAge(100);

?

System.out.println("修改之后");

System.out.println("name=" + p.getName() + ", age =" + p.getAge());

System.out.println("name=" + objP.getName() + ", age =" + objP.getAge());

?

System.out.println("==================================");

System.out.println("看对象中的引用属性");

?

System.out.println("-------修改之前------");

System.out.println("叫兽的name=" + s1.getP().getName());

System.out.println("叫兽的name=" + s2.getP().getName());

?

s2.getP().setName(".......");

?

System.out.println("-------修改之后-----");

System.out.println("叫兽的name=" + s1.getP().getName());

System.out.println("叫兽的name=" + s2.getP().getName());

?

}

}

?

打印的结果:

?

修改之前

name=old, age =50

name=old, age =50

修改之后

name=hahaha, age =50

name=old, age =100

==================================

看对象中的引用属性

-------修改之前------

叫兽的name=hahaha

叫兽的name=old

-------修改之后-----

叫兽的name=hahaha

叫兽的name=.......

?

自己也是刚刚接触,如果有什么问题,请各位及时提出,并批评指正。

发表评论
用户名: 匿名