java里的复制

1、Java中的一般复制操作

      java里的每一个对象以引用的方式进行操作,每次赋值操作涉及的也只是将一个对象的引用赋值,这样的结果是让这个对象多了一个引用而已。例如

      class A {}
       A obj1 = new A() ;

       A obj2 = obj1;//

      上面obj1和obj2其实都是指向同一个内存对象,这样对obj1的修改也会反应到obj2中。

      而java中涉及到的很多数组的复制函数都是这种类型的浅复制(仅复制引用,而没有复制引用所指向的实际内存对象)。如 System.arraycopy , Arrays.copyOf,Arrays.fill等,对于java基本类型(short , int , long , float , double , byte , char , boolean),这种复制没关系,但是对于类对象就会出现我们不需要的情况。

       java.lang.System类中

       native void arraycopy( Object[] src , int srcPos , Object[] dst , int dstPos , int length ) ;该函数把src里的对象复制到dst中,其中复制的也只是引用

       java.util.Arrays类中

       <T> T[] copyOf(T[] original , int newLength ) ;该函数虽然会新建一个数组,并将original数组中的内容复制到新建数组中并返回,但是其中的复制也只是浅复制

       void fill(Object[] a , Object val ) ;//将val填充到a中,此时将val引用复制到a中每个元素,这样其实是a中每个元素都只是对同一个内存对象的引用

       比如:

class Point implements Cloneable {
	private int x , y ;

	public Point( int x , int y ) {
		this.x = x ; this.y = y ;
	}

	public String toString() {
		return "("+this.x + "," + this.y + ")" ;
	}

	public void modify( int newX , int newY ) {
		this.x = newX ; this.y = newY ;
	}	
}

public class ArrayCopy {
	public static void main( String[] args ) {
		Point[] pointArray = new Point[5] ;

		Point p1 = new Point( 1 , 1 ) ;

		Arrays.fill( pointArray , p1 ) ;

		System.out.println( Arrays.deepToString( pointArray) ) ;

		System.out.println() ;

		pointArray[0].modify( 2 , 3 ) ;
		System.out.println( Arrays.deepToString( pointArray ) ) ;

		Point[] pointArray2 = new Point[4] ;
		System.arraycopy( pointArray , 0 , pointArray2 , 0 , 4 ) ;
		System.out.println( Arrays.deepToString( pointArray2 )) ;

		pointArray2[1].modify( 3 , 5 ) ;
		System.out.println(Arrays.deepToString( pointArray2 )) ;

		Point[] pointArray3 = Arrays.copyOf( pointArray2 , 4 ) ;
		System.out.println( Arrays.deepToString( pointArray3 )) ;
		pointArray3[2].modify( 0 , 0 ) ;
		System.out.println( Arrays.deepToString( pointArray3 )) ;

		System.out.println( p1 ) ;		
	}
}
此时输出结果为

[(1,1), (1,1), (1,1), (1,1), (1,1)]

[(2,3), (2,3), (2,3), (2,3), (2,3)]
[(2,3), (2,3), (2,3), (2,3)]
[(3,5), (3,5), (3,5), (3,5)]
[(3,5), (3,5), (3,5), (3,5)]
[(0,0), (0,0), (0,0), (0,0)]
(0,0)

这说明,在每次数组复制时都只是对引用的复制


2、实现java的深复制

利用java的基类Object中的clone方法。

⑴clone方法将对象复制了一份并返回给调用者(其实,此时的复制也是浅复制,若被复制的对象里含有非基本类型的对象,那么此时复制时也只是对引用进行复制)。一般而言,clone()方法满足:
①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象
②对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样
③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。

⑵Java中对象的克隆
①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法(该clone()方法为protected,若想类实现clone必须将其申明为public类型)。
②在派生类中覆盖基类的clone()方法,并声明为public。
③在派生类的clone()方法中,调用super.clone(),同时对该被复制对象里的非基本类型对象调用其自身的clone()函数(当然必须保证这种类型本身已经实现了clone接口)。
④在派生类中实现Cloneable接口。

那么通过clone函数得到的复制对象可以获得深复制效果,比如

class Point implements Cloneable {//该类实现了clone函数
	private int x , y ;

	public Point( int x , int y ) {
		this.x = x ; this.y = y ;
	}

	public String toString() {
		return "("+this.x + "," + this.y + ")" ;
	}

	public void modify( int newX , int newY ) {
		this.x = newX ; this.y = newY ;
	}

	public Object clone() throws CloneNotSupportedException{
		Point result ;

		try{
			result = (Point)super.clone() ;
		}catch ( CloneNotSupportedException e ) {
			throw e ;
		}

		return result ;
	}
}

class PointNoClone {//没有实现clone函数
	private int x , y ;

	public PointNoClone( int x , int y ) {
		this.x = x ; this.y = y ;
	}

	public void modify( int x , int y ) {
		this.x = x ; this.y = y ;
	} 

	public String toString() {
		return "(" + this.x + "," + this.y + ")" ;
	}
}

class PointHolder implements Cloneable {
	private Point point ;
	private PointNoClone pointNoclone ;

	public PointHolder ( Point p , PointNoClone p2 ) {
		this.point = p ;
		this.pointNoclone = p2 ;
	}

	public Object clone() throws CloneNotSupportedException {
		PointHolder result ;

		try{
			result = (PointHolder)super.clone() ;
			result.point = (Point)this.point.clone() ;
		}catch( CloneNotSupportedException e ) {
			throw e ;
		}


		return result ;
	}

	public Point getPoint() {
		return this.point ;
	}

	public PointNoClone getPointNoClone() {
		return this.pointNoclone ;
	}

	public String toString() {
		return "point:" + point.toString() + "\npointNoclone:" + pointNoclone.toString() ;
	}
}

public class ArrayCopy {
	public static void main( String[] args ) {		

		PointHolder pointHolder = new PointHolder( new Point( 20 , 20 ) , new PointNoClone( 15 , 15)) ;

		PointHolder copyPointHolder = null ;
		try{
			copyPointHolder = (PointHolder)pointHolder.clone() ;
		}catch( CloneNotSupportedException e ) {
			e.printStackTrace() ;
		}

		copyPointHolder.getPoint().modify( 30 , 30 ) ;
		copyPointHolder.getPointNoClone().modify( 25 , 25) ;

		System.out.println("pointHolder\n" + pointHolder ) ;
		System.out.println("copyPointHolder\n" + copyPointHolder) ;

	}
}
运行结果为:

pointHolder
point:(20,20)
pointNoclone:(25,25)
copyPointHolder
point:(30,30)
pointNoclone:(25,25)


在PointHolder中实现了clone的对象得到了深复制的效果,而没有实现clone的pointNoClone只是浅复制


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值