深拷贝和浅拷贝(完整实例)

深拷贝和浅拷贝

  1、浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。

在这里插入图片描述

  2、深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。

在这里插入图片描述

  3、浅拷贝(clone)示例代码

public class Student implements Cloneable
{
    private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + "]";
	}
	
	@Override
	public Object clone() throws CloneNotSupportedException
	{
		return super.clone();
	}
	
	
}
public class Teacher implements Cloneable
{
	    private String name;
        private Student student;
		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public Student getStudent() {
			return student;
		}

		public void setStudent(Student student) {
			this.student = student;
		}
		

		@Override
		public String toString() {
			return "Teacher [name=" + name + ", student=" + student + "]";
		}
		@Override
		public Object clone() throws CloneNotSupportedException
		{
			return super.clone();
		}
		
		
}

public class Test 
{
    public static void main(String[] args) 
    {
		Teacher wangLaoShi = new Teacher();
		wangLaoShi.setName("王");
		Student student1 = new Student();
		student1.setName("张三");
		wangLaoShi.setStudent(student1);
		System.out.println();
		
		// 打印结果一样 初步证明使用clone浅拷贝成功
		Teacher xLaoShi = new Teacher();
		try 
		{
			xLaoShi = (Teacher) wangLaoShi.clone();
		} catch (CloneNotSupportedException e)
		{
			e.printStackTrace();
		}
		System.out.println(xLaoShi);
		System.out.println(wangLaoShi);
	    /*
			Teacher [name=王, student=Student [name=张三]]
			Teacher [name=王, student=Student [name=张三]]
	     */
		
		
		// 修改原老师的姓名和学生的姓名,复制的x老师的老师姓名没有跟着变化,学生姓名跟着原老师的学生姓名变化,证明是浅拷贝。
		wangLaoShi.setName("张");
		wangLaoShi.getStudent().setName("李四");
		System.out.println(xLaoShi);
		System.out.println(wangLaoShi);
		
	    /*
			Teacher [name=王, student=Student [name=李四]]
            Teacher [name=张, student=Student [name=李四]]
	     */
	}
}

  4、深拷贝(clone)示例代码

public class Student implements Cloneable
{
    private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + "]";
	}
	
	@Override
	public Student clone() throws CloneNotSupportedException
	{
		return (Student)super.clone();
	}
	
	
}

public class Teacher implements Cloneable
{
	    private String name;
        private Student student;
		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public Student getStudent() {
			return student;
		}

		public void setStudent(Student student) {
			this.student = student;
		}
		

		@Override
		public String toString() {
			return "Teacher [name=" + name + ", student=" + student + "]";
		}
		@Override
		public Teacher clone() throws CloneNotSupportedException
		{
			Teacher teacher = (Teacher) super.clone();
			teacher.setStudent((Student)teacher.getStudent().clone());
			return teacher;
		}
		
		
}

public class Test 
{
    public static void main(String[] args) 
    {
		Teacher wangLaoShi = new Teacher();
		wangLaoShi.setName("王");
		Student student1 = new Student();
		student1.setName("张三");
		wangLaoShi.setStudent(student1);
		System.out.println();
		
		// 打印结果一样 初步证明使用clone深拷贝成功
		Teacher xLaoShi = new Teacher();
		try 
		{
			xLaoShi = wangLaoShi.clone();
		} catch (CloneNotSupportedException e)
		{
			e.printStackTrace();
		}
		System.out.println(xLaoShi);
		System.out.println(wangLaoShi);
	    /*
			Teacher [name=王, student=Student [name=张三]]
			Teacher [name=王, student=Student [name=张三]]
	     */
		
		
		// 修改原老师的姓名和学生的姓名,复制的x老师的老师姓名,学生姓名没有跟着变化,证明是深拷贝。
		wangLaoShi.setName("张");
		wangLaoShi.getStudent().setName("李四");
		System.out.println(xLaoShi);
		System.out.println(wangLaoShi);
		
	    /*
		    Teacher [name=王, student=Student [name=张三]]
            Teacher [name=张, student=Student [name=李四]]
	     */
	}
}

  5、深拷贝(序列化)示例代码

public class Student implements Serializable
{
    /**
	 * 
	 */
	private static final long serialVersionUID = 2808612254630368408L;
	
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + "]";
	}
	
	
	
}

public class Teacher  implements Serializable
{
	    /**
	    * 
	    */
	    private static final long serialVersionUID = 3337955056649739635L;
		private String name;
        private Student student;
		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public Student getStudent() {
			return student;
		}

		public void setStudent(Student student) {
			this.student = student;
		}
		

		@Override
		public String toString() {
			return "Teacher [name=" + name + ", student=" + student + "]";
		}

		
		
}

public class Test 
{
    @SuppressWarnings("resource")
	public static void main(String[] args) 
    {
		Teacher wangLaoShi = new Teacher();
		wangLaoShi.setName("王");
		Student student1 = new Student();
		student1.setName("张三");
		wangLaoShi.setStudent(student1);
		System.out.println();
		try 
		{
			//序列化
			OutputStream outputStream = new FileOutputStream(new File("E:/Teacher.txt"));
			ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
			objectOutputStream.writeObject(wangLaoShi);
			
			//反序列化
			InputStream inputStream = new FileInputStream(new File("E:/Teacher.txt"));
			ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
			Teacher xLaoShi = (Teacher) objectInputStream.readObject();
			
			//打印结果一样 初步证明序列化深拷贝成功
			System.out.println(xLaoShi);
			System.out.println(wangLaoShi);
			 /*
					Teacher [name=王, student=Student [name=张三]]
					Teacher [name=王, student=Student [name=张三]]
		     */
			
			// 修改原老师的姓名和学生,复制的x老师,没有跟着变化,证明使用序列化深拷贝成功。
			wangLaoShi.setName("张");
			wangLaoShi.getStudent().setName("李四");
			System.out.println(xLaoShi);
			System.out.println(wangLaoShi);
			
		    /*
				Teacher [name=王, student=Student [name=张三]]
	            Teacher [name=张, student=Student [name=李四]]
		     */
			
			
			
		} catch (Exception e) 
		{
			e.printStackTrace();
		}
	
	 
	}
}

  6、深拷贝(自定义)示例代码

public class Student 
{
    private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + "]";
	}
	
	
}

public class Teacher 
{
	    private String name;
        private Student student;
		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public Student getStudent() {
			return student;
		}

		public void setStudent(Student student) {
			this.student = student;
		}
		
		public Teacher copy(Teacher teacher)
		{
			 Student student = new Student();
			 student.setName(teacher.getStudent().getName());
			 this.student = student;
			 this.name = teacher.getName();
			 return teacher;
		}

		@Override
		public String toString() {
			return "Teacher [name=" + name + ", student=" + student + "]";
		}
		
		
}

public class Test 
{
    public static void main(String[] args) 
    {
		Teacher wangLaoShi = new Teacher();
		wangLaoShi.setName("王");
		Student student1 = new Student();
		student1.setName("张三");
		wangLaoShi.setStudent(student1);
		System.out.println();
		
		// 打印结果一样 初步证明自定义深拷贝成功
		Teacher xLaoShi = new Teacher();
		xLaoShi.copy(wangLaoShi);
		System.out.println(xLaoShi);
		System.out.println(wangLaoShi);
	    /*
			Teacher [name=王, student=Student [name=张三]]
			Teacher [name=王, student=Student [name=张三]]
	     */
		
		
		// 修改原老师的姓名和学生,复制的x老师,没有跟着变化,证明自定义深拷贝成功。
		wangLaoShi.setName("张");
		wangLaoShi.getStudent().setName("李四");
		System.out.println(xLaoShi);
		System.out.println(wangLaoShi);
		
	    /*
			Teacher [name=王, student=Student [name=张三]]
            Teacher [name=张, student=Student [name=李四]]
	     */
	}
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C++ 中,当一个类的对象被复制时,有两种拷贝方式:浅拷贝深拷贝浅拷贝是指将一个对象的数据成员逐个地复制到另一个对象中,这样两个对象共享同一块内存空间。如果其中一个对象修改了这块内存,那么另一个对象也会受到影响。 深拷贝是指将一个对象的数据成员逐个地复制到另一个对象中,但是对于指针类型的数据成员,会为它们分配新的内存空间,并将原来指针指向的内容复制到新的内存空间中。这样两个对象拥有独立的内存空间,彼此之间互不干扰。 以下是一个浅拷贝深拷贝实例: ```cpp #include <iostream> #include <cstring> class Person { public: Person(const char* n, int a) : age(a) { name = new char[strlen(n) + 1]; strcpy(name, n); } // 拷贝构造函数 Person(const Person& other) { age = other.age; name = other.name; } // 析构函数 ~Person() { delete[] name; } // 输出信息 void printInfo() { std::cout << "Name: " << name << ", Age: " << age << std::endl; } private: char* name; int age; }; int main() { Person p1("Tom", 20); Person p2 = p1; // 浅拷贝 p1.printInfo(); // 输出 "Name: Tom, Age: 20" p2.printInfo(); // 输出 "Name: Tom, Age: 20" p1.~Person(); // 销毁 p1 的 name 指针 p2.printInfo(); // 输出 "Name: Tom, Age: 20",name 指针已被销毁,p2 中的 name 指针变成了野指针 return 0; } ``` 上述代码中,我们定义了一个 Person 类,其中有一个字符串类型的数据成员 name。在拷贝构造函数中,我们只是简单地将 age 和 name 的值从一个对象复制到了另一个对象中,这是一种浅拷贝。当 p1 被销毁时,它的 name 指针被释放了。由于 p2 和 p1 共享同一块内存空间,所以当 p2.printInfo() 被调用时,name 指针已经被销毁,p2 中的 name 指针变成了野指针。 接下来是深拷贝实现: ```cpp #include <iostream> #include <cstring> class Person { public: Person(const char* n, int a) : age(a) { name = new char[strlen(n) + 1]; strcpy(name, n); } // 拷贝构造函数 Person(const Person& other) { age = other.age; name = new char[strlen(other.name) + 1]; strcpy(name, other.name); } // 析构函数 ~Person() { delete[] name; } // 输出信息 void printInfo() { std::cout << "Name: " << name << ", Age: " << age << std::endl; } private: char* name; int age; }; int main() { Person p1("Tom", 20); Person p2 = p1; // 深拷贝 p1.printInfo(); // 输出 "Name: Tom, Age: 20" p2.printInfo(); // 输出 "Name: Tom, Age: 20" p1.~Person(); // 销毁 p1 的 name 指针 p2.printInfo(); // 输出 "Name: Tom, Age: 20",name 指针已经被复制,不会出现野指针 return 0; } ``` 上述代码中,在拷贝构造函数中我们不仅将 age 和 name 的值从一个对象复制到了另一个对象中,还为 name 分配了新的内存空间,并将原来指针指向的内容复制到新的内存空间中。这样两个对象拥有独立的内存空间,彼此之间互不干扰。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值