JAVA入门学习(九)—— 对浅拷贝与深拷贝的理解

一、垃圾回收机制:

低级线程:主要负责堆内存对象的回收,没有引言变量引用,
		引用变量赋值为空,标识对象可以回收,但是不马上回收

	内存溢出:创建对象时,内存不够用
	内存泄漏:对象使用完成,没有及时回收

二、常用的工具包

java.lang:String、System、Thread、Math、Object等,自动导入
java.io:输入输出流
java.net:网络编程
java.util :工具类,集合,时间日期类等


对浅拷贝与深拷贝的理解 (此处是通过重写clone()方法来实现)

浅拷贝与深拷贝详解

Java中的对象拷贝(Object Copy)指的是将一个对象的所有属性(成员变量)拷贝到另一个有着相同类类型的对象中去。举例说明:比如,对象A和对象B都属于类S,具有属性a和b。那么对对象A进行拷贝操作赋值给对象B就是:B.a=A.a; B.b=A.b;

在程序中拷贝对象是很常见的,主要是为了在新的上下文环境中复用现有对象的部分或全部 数据

Java中的对象拷贝主要分为:浅拷贝(Shallow Copy)、深拷贝(Deep Copy)

先介绍一点铺垫知识:Java中的数据类型分为基本数据类型和引用数据类型。对于这两种数据类型,在进行赋值操作、用作方法参数或返回值时,会有值传递和引用(地址)传递的差别

★浅拷贝:

①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。
②对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。

直接上代码:

/**
 * 定义一个student类
 * 创建一个对象。clone克隆对象
 * clone()方法的使用规则
 * 1.自定义的类使用clone方法时,当前类必须要实现cloneable接口,
 * 		如果不实现此接口,那么会抛出异常CloneNotSupportedException
 * 2.因为父类的object类的clone方法是protected修饰,要重写此方法,才能在不同包中访问,把访问修饰符定义为public
 * 3.Cloneable接口没有方法,只是一个标识性的接口,针对object类的clone方法实现
 * 4.浅拷贝:引用变量拷贝的是地址,所有克隆的对象改变了对象的属性,原对象的属性也发生改变
 * 5.深拷贝,引用变量拷贝一份对象,克隆对象的属性改变,原对象的属性不发生改变
 * @author Administrator
 *
 */
public class Student implements Cloneable {

	private int age;
	private Professor professor;

	
	public Professor getProfessor() {
		return professor;
	}

	public void setProfessor(Professor professor) {
		this.professor = professor;
	}

	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();
	}
}

public class Professor {

	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}	
}

/**
 * 测试浅拷贝
 */
public class Test01 {

	public static void main(String[] args) throws CloneNotSupportedException {
		
		//实现了基本数据age和引用类型Professor的浅拷贝
		Student stu = new Student();
		stu.setAge(9);
		Professor professor = new Professor();
		stu.setProfessor(professor);
		stu.getProfessor().setAge(20);
		System.out.println(stu.getAge());
		
		//通过调用重写后的clone方法进行浅拷贝
		Student stu2 = (Student) stu.clone();
		stu2.setAge(10);
		stu2.getProfessor().setAge(30);
		System.out.println(stu2.getAge());
		
		System.out.println("------------");
		System.out.println(stu.getProfessor().getAge());
		System.out.println(stu2.getProfessor().getAge());
	}
}

//结果
9
10    基本数据类型clone后,原值没有随着变化而改变
------------
30
30    引用数据类型clone后,原值随着变化也变化

★深拷贝:

首先介绍对象图的概念。设想一下,一个类有一个对象,其成员变量中又有一个对象,该对象指向另一个对象,另一个对象又指向另一个对象,直到一个确定的实例。这就形成了对象图。那么,对于深拷贝来说,不仅要复制对象的所有基本数据类型的成员变量值,还要为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象图进行拷贝!

简单地说,深拷贝对引用数据类型的成员变量的对象图中所有的对象都开辟了内存空间;而浅拷贝只是传递地址指向,新的对象并没有对引用数据类型创建内存空间。

public class Professor implements Cloneable {

	private int age;

	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();
	}
	
}

public class Student implements Cloneable {

	private int age;
	private Professor professor;

	
	public Professor getProfessor() {
		return professor;
	}

	public void setProfessor(Professor professor) {
		this.professor = professor;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
		//拷贝Student的数据
		Student stu = (Student) super.clone();
		//拷贝Professor的数据
		stu.professor = (Professor) stu.getProfessor().clone();
		return stu;
	}
}

/**
 * 测试深拷贝
 */
public class Test01 {

	public static void main(String[] args) throws CloneNotSupportedException {
		
		//实现了基本数据age和引用类型Professor的深拷贝
		Student stu = new Student();
		stu.setAge(9);
		Professor professor = new Professor();
		stu.setProfessor(professor);
		stu.getProfessor().setAge(20);
		System.out.println(stu.getAge());
		
		Student stu2 = (Student) stu.clone();
		stu2.setAge(10);
		stu2.getProfessor().setAge(30);
		System.out.println(stu2.getAge());
		
		System.out.println("------------");
		System.out.println(stu.getProfessor().getAge());
		System.out.println(stu2.getProfessor().getAge());
	}
}


结果:
9
10	  基本数据类型——原值没改变
------------
20
30   引用数据类型——原值没改变

你可能感兴趣的:(java,java)