黑马程序员技术交流社区
标题:
克隆问题
[打印本页]
作者:
阳羽
时间:
2011-9-21 19:13
标题:
克隆问题
深克隆与浅克隆的区别?
作者:
匿名
时间:
2011-9-21 19:17
标题:
回复 楼主 的帖子
浅克隆:就是被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。就是说浅克隆只复制了当前的对象得字段的逐字段拷贝,对当前的对象的引用还是指向以前的。
深克隆:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
深克隆与浅克隆的区别:浅克隆不用序列化,这种克隆方式仅仅只是将指定的当前对象复制出来一个,这种复制过程不包括原对象引用的各个对象,引用的对象不变。深克隆的过程是通过序列化来完成的,而序列化的过程可以将对象及所牵涉的所有引用链中的对象一起通过字节流的方式转移到特定的存储,再通过反序列化的过程读出这些序列化的字节流重构出对象,这样就完成了一个新对象的产生。
Java的clone()方法
2.1 clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:
①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象
②对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样
③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
2.2 Java中对象的克隆
①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。
②在派生类中覆盖基类的clone()方法,并声明为public。
③在派生类的clone()方法中,调用super.clone()。
④在派生类中实现Cloneable接口。
自己不太会说,网上找了一段。
作者:
匿名
时间:
2011-9-21 21:51
这是我以前写的深克隆的例子,里面有我自己理解的注释,给你看看吧,希望对你有用。也谢谢你让我也复习了一下clone。
/**
[color=Red] * 重写Object类的clone()但是没有实现深克隆,这里虽然形式上重写了object类的clone()方法
* 但是并没有是指性代码,其实还是沿用的object类的clone()方法
* 还可以用序列化的方式实现深克隆详见 :SerrialazableTest2.java[/color] *
* @author Administrator
*
*/
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person();
p1.setName("张三");
p1.setAge(10);
Person p2 = (Person) p1.clone();
System.out.println(p2.getName());
p1.setName("aaa");//name属性是引用类型的所以只是将引用克隆了一份,引用所指向的对象并不复制,
//所以复制以后改变了原来引用对象的值,克隆以后的新对象的引用值也发生了改变
//这里虽然形式上已经重写了clone()但是并没有实质性的代码,所以还是沿用的object类的clone()方法
p1.setAge(11);//浅克隆会将非引用类型克隆一份,因为age是值类型 ,所以会被克隆一份新的
System.out.println(p2.getAge());
System.out.println(p2.getName());//name属性是引用类型的所以只是将引用复制一份,引用所指向的值不变
}
}
class Person implements Cloneable {
private String name;
private int age;
public Person() {
}
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();
}
//@Override//这里重写Object类的clone()实现了深克隆
// protected Object clone() throws CloneNotSupportedException {
// Person p=(Person)super.clone();
//
// return p;
// }
}
作者:
匿名
时间:
2011-9-21 21:55
刚才那个程序是潜克隆,这个是我用序列化方式实现的深克隆
import java.io.ByteArrayInputStream;
/**
*
* 程序说明,本例子通过序列化实现深克隆
*
* @author Administrator
*
*/
public class SerialazableTest2 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Student s1=new Student("jack",10);
s1.setDog(new Dog("阿笨"));
Student s2=(Student)s1.deepCopy();
s1.setDog(new Dog("阿扁"));//这里已经实现了深克隆了所以s1的改变不会影响到s2的引用
System.out.println(s2.getDog().getName());
}
}
class Student implements Serializable{
private String name;
private int age;
private Dog dog;
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student (){}
public Student(String name,int age){
this.name=name;
this.age=age;
}
public Object deepCopy() throws IOException, ClassNotFoundException{
//使用FileOutputStream这个节点流是一定要写入文件的,这里写入文件也没有多大用处,所以适用ByteArrayOutputStream
File file=new File("text.txt");
FileOutputStream fos=new FileOutputStream(file);
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(this);
FileInputStream fis=new FileInputStream(file);
ObjectInputStream ois=new ObjectInputStream(fis);
Object obj=ois.readObject();
ois.close();
//这里使用ByteArrayOutputStream更好,因为这样就不用写到文件中了,只是写到内存中,不用创建文件了
// ByteArrayOutputStream baos=new ByteArrayOutputStream();
// ObjectOutputStream oos=new ObjectOutputStream(baos);
// oos.writeObject(this);
// ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
// ObjectInputStream ois=new ObjectInputStream(bais);
// Object obj=ois.readObject();
// ois.close();
//
return obj;
}
}
class Dog implements Serializable{//被包含的引用对象也要实现可序列化接口,如果不想被序列化用transient标示
private String name;//transient如果这里用transient标示了,那么就表示不能被序列化了,将显示null
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Dog(String name){
this.name=name;
}
}
作者:
王毛毛
时间:
2011-9-22 09:38
浅克隆:就是被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。就是说浅克隆只复制了当前的对象得字段的逐字段拷贝,对当前的对象的引用还是指向以前的。
深克隆:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
深克隆与浅克隆的区别:浅克隆不用序列化,这种克隆方式仅仅只是将指定的当前对象复制出来一个,这种复制过程不包括原对象引用的各个对象,引用的对象不变。深克隆的过程是通过序列化来完成的,而序列化的过程可以将对象及所牵涉的所有引用链中的对象一起通过字节流的方式转移到特定的存储,再通过反序列化的过程读出这些序列化的字节流重构出对象,这样就完成了一个新对象的产生。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2