Java中除了基本类型int,char,double等的赋值是按照值传递之外,其余的类型和对象都是按照引用进行传递的。

  下面来看一个关于引用的例子。  

package referenceCopy;
// 一个文件中允许有多个类,但是public类型的类只能有一个
class Basic {
 private int aInt = 0;
 public int getAInt() {
 return aInt;
 }
 public void setAInt(int int1) {
 aInt =int1;
 }
 public void changeInt() {
 this.aInt = 1;
 }
}
public class Children {
 // int char double 等基本类型都是按照值传递的,
 // 除此之外的其他类型都是按照引用进行传递的。
 public static void main(String[] args) {
 // TODO Auto-generated method stub
 Basic b = new Basic();
 Basic a = b;
 b.changeInt();
 System.out.println(b.getAInt());
 System.out.println(a.getAInt());
 }}

输出的结果为1,1

究其原因是a和b的指向同一个引用。 

那么如何变成两个引用呢,我们提出了浅复制和深复制。

首先我们来看浅复制

package referenceCopy;
import java.util.Date;
// 一个文件中允许有多个类,但是public类型的类只能有一个
class BasicA implements Cloneable{
 private int aInt = 0;

 private Date birth = new Date();

 public Date getBirth() {
 return birth;
 }
 public void setBirth(Date birth) {
 this.birth = birth;
 }
 public void changeBirth() {
 this.birth.setMonth(1);
 }
 public int getAInt() {
 return aInt;
 }
 public void setAInt(int int1) {
 aInt =int1;
 }
 public void changeInt() {
 this.aInt = 1;
 }
 // 改写clone方法
 public Object clone() {
Object o = null;
 try {
 o = (BasicA)super.clone();
 } catch (Exception e) {
 e.printStackTrace();
 }
 return o;
 }
}
public class WeakChildrenReferneceCopy {
 // int char double 等基本类型都是按照值传递的,
 // 除此之外的其他类型都是按照引用进行传递的。
 // 相对于Children类,该类采用了浅复制的方法来进行复制。
 // 基本的数据类型变量已经全部复制了进来,但是具体对象的改变并未改变
 public static void main(String[] args) {
 BasicA b = new BasicA();
 BasicA a = (BasicA)b.clone();
 b.changeInt();
 b.changeBirth();
 // 由此可见,浅复制只复制了简单的数据类型,
 // 对于复杂的数据类型并未进行复制
 System.out.println(a.getAInt());
 System.out.println(b.getAInt());
 System.out.println(b.getBirth());
 System.out.println(a.getBirth());
 }}

输出的结果如下所示:

0
1
Mon Feb 06 14:45:47 CST 2017
Mon Feb 06 14:45:47 CST 2017

由结果可以看出,浅复制并未改变其他对象的引用。 

由此,我们提出了深复制

package referenceCopy;
import java.util.Date;
//一个文件中允许有多个类,但是public类型的类只能有一个
class BasicB implements Cloneable{
 private int aInt = 0;

 private Date birth = new Date();

 public Date getBirth() {
 return birth;
 }
 public void setBirth(Date birth) {
 this.birth = birth;
 }
 public void changeBirth() {
 this.birth.setMonth(1);
 }
 public int getAInt() {
 return aInt;
 }
 public void setAInt(int int1) {
 aInt =int1;
 }
 public void changeInt() {
 this.aInt = 1;
 }
 // 改写clone方法
 public Object clone() {
 // 强复制需要将返回的复制对象改变为自己需要的对象
BasicB o = null;
 try {
 o = (BasicB)super.clone();
 } catch (CloneNotSupportedException e) {
 e.printStackTrace();
 }
 o.birth = (Date)this.getBirth().clone();
 return o;
 }
}
public class StrongChildrenReferenceCopy {
 public static void main(String[] args) {
 BasicB a = new BasicB();
 BasicB b = (BasicB) a.clone();
 b.changeInt();
 b.changeBirth();
 System.out.println(a.getAInt());
 System.out.println(b.getAInt());
 System.out.println(a.getBirth());
 System.out.println(b.getBirth());
 }}
运行结果如下:
0
1
Thu Jul 06 14:55:13 CST 2017
Mon Feb 06 14:55:13 CST 2017

由上处进行了标红的地方可以看出两者在进行复制时的不同之处。

浅复制:被复制的对象的所有 变量都含有与原来对象相同的值,而所有对其他对象的引用仍然指向原来对象相同的值。换言之,浅复制只复制自己考虑的对象,未复制它所引用的对象。

深复制:被复制对象的所有变量都含有与原来对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制的新对象,而不是原有的那些被引用的对象,换言之,深复制把复制对象 所引用的对象都复制了一遍。