为什么我们需要复制构造函数以及我们什么时候应该在java中使用复制构造函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29362169/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why do we need copy constructor and when should we use copy constructor in java
提问by Avinash Reddy
I was going through Copy Constructors, I have gone through the links in stack over flow and others as well. But i am not clear on the following points.
我正在浏览复制构造函数,我也浏览了堆栈溢出和其他链接中的链接。但我不清楚以下几点。
- Why do we need a Copy Constructor
- When do we need a Copy Constructor
- 为什么我们需要复制构造函数
- 我们什么时候需要复制构造函数
I mean what is the exact situation or scenario we would need to use Copy Constructor. Can some one explain with an example or point out links so that i can go through and understand them in clear.
我的意思是我们需要使用 Copy Constructor 的确切情况或场景是什么。有人可以用一个例子来解释或指出链接,以便我可以清楚地了解并理解它们。
Following are the links i have gone through to get an understanding of what is a copy constructor.
以下是我为了解什么是复制构造函数而浏览的链接。
http://www.programmerinterview.com/index.php/java-questions/how-copy-constructors-work/
http://www.programmerinterview.com/index.php/java-questions/how-copy-constructors-work/
https://deepeshdarshan.wordpress.com/2013/12/05/copy-constructors-in-java/
https://deepeshdarshan.wordpress.com/2013/12/05/copy-constructors-in-java/
The second link explains 'why' and 'where' the copy constructor is to be used. But still i am not clear on it.
第二个链接解释了“为什么”和“在哪里”使用复制构造函数。但我仍然不清楚。
Below is my class Employee.java
下面是我的班级 Employee.java
package com.test;
/**
* @author avinashd
*
*/
public class Employee {
private String rollNo;
private String name;
//constructor
public Employee(String rollNo, String name){
this.rollNo = rollNo;
this.name = name;
}
//copy constructor
public Employee(Employee employee){
this.rollNo = employee.rollNo;
this.name = employee.name;
}
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Copy Constructor is used to create and exact copy of an object with the same values of an existing object.
复制构造函数用于创建对象的精确副本,该对象具有与现有对象相同的值。
Say for example we have an Employee with values as rollNo: 1
and name: avinash
. Copy Constructor would create a similar object with values as rollNo: 1
and name: avinash
. But both are 2 different objects and changes to the values of on object will not affect another object.
例如,假设我们有一个值为rollNo: 1
and的 Employee name: avinash
。Copy Constructor 将创建一个类似的对象,其值为rollNo: 1
和name: avinash
。但两者都是 2 个不同的对象,对对象值的更改不会影响另一个对象。
The Question here is
这里的问题是
When we have a constructor such as
当我们有一个构造函数比如
public Employee(String rollNo, String name){
this.rollNo = rollNo;
this.name = name;
}
to create an object. We can call the same constructor to create another object. But why do we need to call copy constructor.When do we need to call it ?. Please explain
创建一个对象。我们可以调用相同的构造函数来创建另一个对象。但是为什么我们需要调用复制构造函数。我们什么时候需要调用它?。请解释
采纳答案by Serge Ballesta
There are 2 good reasons for using a copy constructor instead of the constructor passing all parameters :
使用复制构造函数而不是传递所有参数的构造函数有两个很好的理由:
- when you have a complex object with many attributes it is much simpler to use the copy constructor
- if you add an attribute to your class, you just change the copy constructor to take this new attribute into account instead of changing every occurence of the other constructor
- 当您有一个具有许多属性的复杂对象时,使用复制构造函数要简单得多
- 如果向类添加属性,只需更改复制构造函数以考虑此新属性,而不是更改其他构造函数的每次出现
回答by TheLostMind
What if you want to have another Employee
instance with the exact same values as the one you already have?.
如果您想要另一个Employee
实例与您已有的实例具有完全相同的值怎么办?
Will you call?
你会打电话吗?
setName(oldEmployee.getName())..
setRollNumber(oldEmployee.getRollNumber())..
etc..
Instead of doing that, use this
而不是这样做,使用这个
Employee copyOfEmployeeOne=new Employee(employeeOneInstance);
// no need of a sequence of setters..
回答by zubergu
Another case would be storing object "historical" values.
另一种情况是存储对象“历史”值。
So you have single object but whenever you change its state you want to add it to ArrayList
or whatever data structure fits you best, instead of making manual copy of the data you just use "copy constructor" before further modification.
因此,您只有一个对象,但是每当您更改其状态时,您都希望将其添加到ArrayList
或任何最适合您的数据结构中,而不是手动复制数据,您只需在进一步修改之前使用“复制构造函数”。
回答by skytreader
Copy constructors, by convention, should provide a deep copy of objects. As already mentioned by other answers, the main convenience provided by copy constructors is when your object becomes too complex. Note that java.lang.Cloneable
provides an (almost) similar declaration.
按照惯例,复制构造函数应该提供对象的深层副本。正如其他答案已经提到的,复制构造函数提供的主要便利是当您的对象变得过于复杂时。请注意,它java.lang.Cloneable
提供了(几乎)类似的声明。
But there are a number of advantages to using copy constructors over the Cloneable
interface.
但是在Cloneable
接口上使用复制构造函数有许多优点。
Cloneable
as an interface does not actually provide any methods. For it to be effective, you still need to override theclone
method ofjava.lang.Object
. This is quite a counterintuitive use for an interface.clone
returns anObject
. For it to be of any use, you still need to typecast. This is awkward and could lead to runtime errors.The
clone
method is poorly documented. Forclone
, things can get messed up if you have final fields pointing to mutable objects.Most importantly, copy constructors can take in and deep copy instances of subclasses. IMO, this is where copy constructors really shine.
Cloneable
作为接口实际上不提供任何方法。它是有效的,你仍然需要覆盖clone
的方法java.lang.Object
。对于接口来说,这是一种非常违反直觉的用法。clone
返回一个Object
. 为了它有任何用处,您仍然需要进行类型转换。这很尴尬,可能会导致运行时错误。该
clone
方法没有很好的记录。对于clone
,如果您有指向可变对象的 final 字段,事情可能会变得一团糟。最重要的是,复制构造函数可以接收子类的深度复制实例。IMO,这是复制构造函数真正闪耀的地方。
There are more advantages (see Joshua Bloch's Effective Java 2e) but these are the points which I have found most pertinent to what I have worked on so far.
还有更多优势(请参阅 Joshua Bloch 的Effective Java 2e),但这些是我发现与我迄今为止所做的工作最相关的要点。
[1] Nothing in the Java language actually provides a default construct for deep copying. At most, objects can just tell programmers that they can be deep copied by, say, implementing Cloneable
or providing a copy constructor.
[1] Java 语言中实际上没有任何内容为深度复制提供默认构造。最多,对象只能告诉程序员它们可以通过实现Cloneable
或提供复制构造函数来进行深度复制。
回答by Naresh Joshi
Copy constructors give us many advantages over Object.clone() method because they
与 Object.clone() 方法相比,复制构造函数为我们提供了许多优势,因为它们
- Don't force us to implement any interface or throw an exception.
- Don't require any casts.
- Don't require us to depend on an unknown object creation mechanism.
- Don't require parent class to follow any contract or implement anything.
- Allow us to modify final fields.
- Allow us to have complete control over object creation, we can write our initialization logic in it.
- 不要强迫我们实现任何接口或抛出异常。
- 不需要任何演员表。
- 不要要求我们依赖一个未知的对象创建机制。
- 不要要求父类遵循任何合同或实现任何东西。
- 允许我们修改最终字段。
- 让我们可以完全控制对象的创建,我们可以在其中编写我们的初始化逻辑。
Read more on Java Cloning - Copy Constructor versus Cloning
阅读有关Java 克隆的更多信息- 复制构造函数与克隆
回答by Srikant M
Through Copy constructor We can do cloning with out using much complex stuff like implementing Cloneable interface and overwriting clone method. Also we no need to worry specially about deep cloning.
通过复制构造函数我们可以在不使用很多复杂的东西的情况下进行克隆,比如实现 Cloneable 接口和覆盖克隆方法。我们也无需特别担心深度克隆。
But points to be noted are :
但需要注意的是:
1.When we implement Cloneable, it is an intimation to other classes/users that this class' objects can be cloneable. With out this, Other classes may not have explicit information about cloneable.
1.当我们实现Cloneable时,是对其他类/用户的一个提示,该类的对象可以是可克隆的。没有这个,其他类可能没有关于可克隆的明确信息。
2.If we make our copy constructor as private , then we can restrict cloning of this class' object. Then this copy constructor can only be used to initialize newly created objects in local to class rather than for cloning purpose in other class.
2.如果我们将我们的复制构造函数设为私有,那么我们可以限制对此类对象的克隆。那么这个复制构造函数只能用于在类本地初始化新创建的对象,而不能用于其他类中的克隆目的。
3.When you do not want to make your class cloneable but if you have written copy constructor with access specifier public, then it leads to insecurity that other classes can create objects of your class.
3.当您不想使您的类可克隆但如果您编写了带有访问说明符 public 的复制构造函数时,则会导致其他类可以创建您类的对象的不安全性。
回答by BinDev
Copy Constructors implements both shallow and deep cloning mechanism, but main advantages of using copy constructor over cloning(using Cloneable interface) is:
Copy Constructors 实现了浅层和深层克隆机制,但使用拷贝构造函数优于克隆(使用 Cloneable 接口)的主要优点是:
- We don't require any type casing as of in using Object.clone()method.
- We will be able to modify the final fields for copying purpose unlike we are unable to modify or access final fields in case of Object.clone() mechanism.
- It allows us to have complete control over object creation, we can write our initialization logic in it.
- If we want to clone object of our class that holds reference variable of other dependent class we don't need to implement clone method that class. Simply by initializing our copy constructor, we can achieve that.
- 在使用 Object.clone() 方法时,我们不需要任何类型的大小写。
- 我们将能够出于复制目的修改最终字段,这与我们无法在 Object.clone() 机制的情况下修改或访问最终字段不同。
- 它允许我们完全控制对象的创建,我们可以在其中编写初始化逻辑。
- 如果我们想克隆包含其他依赖类的引用变量的类的对象,我们不需要实现该类的克隆方法。只需初始化我们的复制构造函数,我们就可以实现。
回答by nabster
Consider this example where super class has a copy constructor provided to implicitly force developer to manually copy fields over to parent class. This can be useful for Downcasting:
考虑这个示例,其中超类提供了一个复制构造函数,以隐式强制开发人员手动将字段复制到父类。这对于向下转换很有用:
public class Employee {
private String name;
private int age;
// regular constructor
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
// copy constructor
public Employee(Employee that) {
this.name = that.name;
this.age = that.age;
}
// getters & setters
}
public class SeniorMgmt extends Employee {
private boolean secureAccess;
public SeniorMgmt(Employee employee, boolean secureAccess) {
super(employee);
this.secureAccess = secureAccess;
}
// getters & setters
}
public class TestDrive {
public static void main(String[] args) {
Employee programmer = new Employee("John", 34);
SeniorMgmt promotedProgrammer = new SeniorMgmt(programmer, true);
}
}