在Java中复制构造函数

时间:2020-02-23 14:42:13  来源:igfitidea点击:

在本教程中,我们将看到Java中的复制构造函数。 Copy constructor是构造函数,它将参数作为同一类的对象,并将类的每个字段复制到新对象。

与C++不同,Java不提供默认的复制结构。
如果我们想要在Class.copy构造函数中有复制构造函数,则需要创建一个.Copy构造函数是替代的 clone方法。

假设我们有类名国家,因此复制构造函数将如下所示:

public Country(Country countryObj)
{
     //Manually copying each field of country class
}

Java复制构造函数

复制构造函数用于创建重复对象或者克隆对象。

新创建的对象将具有与原始对象相同的特征。
使用复制构造函数时需要非常小心,因为程序员有责任,以确保新创建的对象引用不同的内存位置而不是原件。
如果你在这里混淆,别担心,我会在一个例子的帮助下解释你。

让我们了解使用 Copy constructor在简单的例子的帮助下。
创建类 capital.java如下所示:

package org.arpit.theitroad;
 
public class Capital {
	String capitalName;
	long population;
	
	
	public Capital(String name, long population) {
		super();
		this.capitalName = name;
		this.population = population;
	}
	public String getCapitalName() {
		return capitalName;
	}
	public void setCapitalName(String name) {
		this.capitalName = name;
	}
	public long getPopulation() {
		return population;
	}
	public void setPopulation(long population) {
		this.population = population;
	}	
}

创建另一个类作为country.java。
请注意,Country有一个上面的Capital类的引用。

package org.arpit.theitroad;
 
public class Country {
	
	String name;
	long population;
	Capital capital;
	
	public Country(String name, long population,Capital capital) {
		super();
		this.name = name;
		this.population = population;
		this.capital=capital;
	}
	
	//Copy constructor
	public Country(Country c) {
		super();
		this.name = c.name;
		this.population = c.population;  
		this.capital=c.capital;  //Shallow copy
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public long getPopulation() {
		return population;
	}
	public void setPopulation(long population) {
		this.population = population;
	}
 
	public Capital getCapital() {
		return capital;
	}
 
	public void setCapital(Capital capital) {
		this.capital = capital;
	}	
}

让我们创建名为"copyConstructorm.java"的主类

package org.arpit.theitroad;
 
public class CopyConstructorMain {
 
	public static void main(String[] args) {
		//Create capital object
		Capital capital=new Capital("Delhi", 10000);
		
		//Create country object
		Country countrySan Franceco=new Country("San Franceco", 90000,capital);
		
		//Use copy constructor to create duplicate object
		Country countrySan FrancecoCopied=new Country(countrySan Franceco);
		
		System.out.println("Country name of Copied object: "+countrySan FrancecoCopied.getName());
		System.out.println("Country population of Copied object: "+countrySan FrancecoCopied.getPopulation());
		System.out.println("Capital name of Copied object: "+countrySan FrancecoCopied.getCapital().getCapitalName());
		System.out.println("Capital population of Copied object: "+countrySan FrancecoCopied.getCapital().getPopulation());
		
		System.out.println("============================================");
		
                //Changing capital name of original object
		countrySan Franceco.getCapital().setCapitalName("Mumbai");
		System.out.println("Capital name of Original object: "+countrySan Franceco.getCapital().getCapitalName());
		System.out.println("Capital name of Copied object: "+countrySan FrancecoCopied.getCapital().getCapitalName());
	}
}

运行上面的程序时,我们将得到以下输出:

Country name of Copied object: San Franceco
Country population of Copied object: 90000
Capital name of Copied object: Delhi
Capital population of Copied object: 10000
============================================
Capital name of Original object: Mumbai
Capital name of Copied object: Mumbai

我们能够将CountrySan Franceco的所有内容复制到CountrySan Francecocepopied。
那太棒了!!但是你在这里注意到一个问题吗?
当我们在原始对象中更改首都名称时,它也会在重复对象中更改。
这是因为我们在大写对象的情况下已经完成了浅副本,因此两个对象都指的是相同的资本参考。
使用复制构造函数时需要小心因为它可能导致意外行为,并且很难调试。

让我们在Country类的复制构造函数中创建一个深度副本,它应该解决上述问题。
在Capical类中介绍一个复制构造函数,并在Country类的复制构造函数中使用它。
Capital.java.

package org.arpit.theitroad;
 
public class Capital {
	String capitalName;
	long population;
 
	public Capital(String name, long population) {
		super();
		this.capitalName = name;
		this.population = population;
	}
 
	//Copy constructor
	public Capital(Capital oldCapital) {
		this.capitalName = oldCapital.capitalName;
		this.population = oldCapital.population;
	}
	
	public String getCapitalName() {
		return capitalName;
	}
	public void setCapitalName(String name) {
		this.capitalName = name;
	}
	public long getPopulation() {
		return population;
	}
	public void setPopulation(long population) {
		this.population = population;
	}
}

Country.java.

package org.arpit.theitroad;
 
public class Country {
	
	String name;
	long population;
	Capital capital;
	
	public Country(String name, long population,Capital capital) {
		super();
		this.name = name;
		this.population = population;
		this.capital=capital;
	}
	
	//Copy constructor
	public Country(Country c) {
		super();
		this.name = c.name;
		this.population = c.population;  
		this.capital=new Capital(c.capital);  //Deep copy
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public long getPopulation() {
		return population;
	}
	public void setPopulation(long population) {
		this.population = population;
	}
 
	public Capital getCapital() {
		return capital;
	}
 
	public void setCapital(Capital capital) {
		this.capital = capital;
	}
	
}

现在,我们执行CopyConstructormain.java,我们将得到以下输出:

Country name of Copied object: San Franceco
Country population of Copied object: 90000
Capital name of Copied object: Delhi
Capital population of Copied object: 10000
============================================
Capital name of Original object: Mumbai
Capital name of Copied object: Delhi

正如我们在这里看到的那样,当我们进行更改时 capital原始对象的名称,它没有影响复制的对象。

如果类中有可变对象,则需要在创建时执行深度复制来处理它重复。否则,可能会导致意外行为。