论坛首页 入门技术论坛

拷贝对象要细心

浏览 2298 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-01-11  
在说对象的拷贝问题之前,先提一下java对参数的传递。在Java语言中通过值传递机制将所有实参的值传递给方法,这就意味着方法将接受所有实参
的一个拷贝,看下面的代码:
	public static void main(String[] args) {
		int i = 1;
		int j = 2;
		change(i,j);
		System.out.println(i+j);
	}
	public static void change(int i, int j){
		i += 10;
		j += 10;
	}

打印结果是3,并不会影响到原来的变量值。但是如果方法接受的实参类型不是基本类型的变量,而是对象,那么Java语言运用的机制就是引用传递。继续看代码:
先定义两个Dog类:
public class Flea{
	private String size;
	public Flea(String size) {
		this.size = size;
	}
}
public class Dog {
	private String name; 
	private int age; 	
	private Flea flea;
	public Dog(String aName,int age) { 
		this.name = aName; 
		this.age = age; 
		this.flea = new Flea("small");		
	}
	public String toString(){
		return "Dog age is "+age+"! Dog's flea size is "+flea.getSize();
	}
}

接着
	public static void main(String[] args) {
		Dog dog = new Dog("Tom",10);
		change(dog);
		System.out.println(dog);
	}
	public static void change(Dog dog){
		dog.setAge(100);
		dog.getFlea().setSize("big");
	}

打印结果应该是Dog age is 100 ! Dog's flea size is big。这是因为传递给方法的变量是一个对象引用的副本,也就是说dog是一个对象的引用,而传递给方法的是dog这个引用的副本,因此二者引用的是同一个对象,因此在方法中对象改变了,那么方法外对象也会改变。这是要做的事情就是在对象传递给方法之前先做拷贝。因此修改一下Dog.java
public class Flea implements Cloneable {
	private String size;
	public Flea(String size) {
		this.size = size;
	}
	public Object clone() {
		Flea newFlea = null;
		try{
			newFlea = super.clone();
		}
		catch(CloneNotSupportedException e){}
		return newFlea;
	}
}
public class Dog implements Cloneable{
	private String name; 
	private int age; 	
	public Dog(String aName, int age) { 
		this.name = aName; 
		this.age = age; 	
		this.flea = new Flea("small");
	}
	public Object clone() {
		Dog newDog = null;
		try{
			newDog = super.clone();
		}
		catch(CloneNotSupportedException e){}
		return newDog;
	}
	public String toString(){
		return "Dog age is "+age+"! Dog's flea size is "+flea.getSize();
	}
}

接下来调整一下测试代码:
	public static void main(String[] args) {
		Dog dog = new Dog("Tom",10);
		Dog cDog = (Dog)dog.clone();
		change(dog);
		System.out.println(dog);
		System.out.println(cDog);
	}

可以看到打印结果是:
Dog age is 100! Dog's flea size is big
Dog age is 10! Dog's flea size is big
这时结果仍然不能让人满意,因为虽然Dog的age被保留了下来,但是Dog的Flea的size确仍然被改变了。这就是需要注意的地方,拷贝对象时留意对象的嵌套对象的拷贝,如此修改一下Dog的clone方法:
	public Object clone() {
		Dog newDog = null;
		try{
			newDog = (Dog)super.clone();
			newDog.flea = (Flea)flea.clone();//加上这一行
		}
		catch(CloneNotSupportedException e){}
		return newDog;
	}

再次运行一次,可以看到结果是:
Dog age is 100! Dog's flea size is big
Dog age is 10! Dog's flea size is small
这样就可以保留在调用方法之前的对象了。^_^
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics