提问人:Avinash Reddy 提问时间:3/31/2015 最后编辑:soufrkAvinash Reddy 更新时间:9/27/2019 访问量:52750
为什么我们需要复制构造函数,什么时候应该在 java 中使用复制构造函数
Why do we need copy constructor and when should we use copy constructor in java
问:
我正在浏览复制构造函数,我也浏览了堆栈流和其他链接。但我不清楚以下几点。
- 为什么我们需要一个复制构造函数
- 我们什么时候需要复制构造函数
我的意思是我们需要使用 Copy Constructor 的确切情况或场景是什么。有人可以举个例子解释一下或指出链接,以便我可以清楚地了解和理解它们。
以下是我为了解什么是复制构造函数而浏览的链接。
http://www.programmerinterview.com/index.php/java-questions/how-copy-constructors-work/
https://deepeshdarshan.wordpress.com/2013/12/05/copy-constructors-in-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;
}
}
复制构造函数用于创建和精确复制具有与现有对象相同的值的对象。
例如,假设我们有一个值为 和 的 Employee。Copy Constructor 将创建一个类似的对象,其值为 和 。但两者都是 2 个不同的对象,对 on 对象值的更改不会影响另一个对象。rollNo: 1
name: avinash
rollNo: 1
name: avinash
这里的问题是
当我们有一个构造函数时,例如
public Employee(String rollNo, String name){
this.rollNo = rollNo;
this.name = name;
}
以创建对象。我们可以调用相同的构造函数来创建另一个对象。但是为什么我们需要调用复制构造函数呢?我们什么时候需要调用它?请解释
答:
如果您想拥有另一个与已有实例具有完全相同的值的实例,该怎么办?Employee
你会打电话吗?
setName(oldEmployee.getName())..
setRollNumber(oldEmployee.getRollNumber())..
etc..
与其这样做,不如使用它
Employee copyOfEmployeeOne=new Employee(employeeOneInstance);
// no need of a sequence of setters..
评论
使用复制构造函数而不是传递所有参数的构造函数有 2 个很好的理由:
- 当您有一个具有许多属性的复杂对象时,使用 Copy 构造函数要简单得多
- 如果将属性添加到类中,则只需更改复制构造函数以考虑此新属性,而不是更改其他构造函数的每次匹配
另一种情况是存储对象的“历史”值。
因此,您有一个对象,但每当您更改其状态时,您都希望将其添加到最适合您的任何数据结构中,而不是手动复制数据,您只需在进一步修改之前使用“复制构造函数”。ArrayList
按照惯例,复制构造函数应提供对象的深层副本。正如其他答案中已经提到的,复制构造函数提供的主要便利是当你的对象变得过于复杂时。请注意,它提供了(几乎)类似的声明。java.lang.Cloneable
但是,在接口上使用复制构造函数有许多优点。Cloneable
Cloneable
因为接口实际上不提供任何方法。要使它有效,您仍然需要重写 .对于界面来说,这是一个非常违反直觉的用途。clone
java.lang.Object
clone
返回一个 .要使它有任何用处,您仍然需要进行类型转换。这很尴尬,可能会导致运行时错误。Object
该方法的记录很少。对于 ,如果最终字段指向可变对象,事情可能会搞砸。
clone
clone
最重要的是,复制构造函数可以接受子类的深度复制实例。IMO,这是复制构造函数真正闪耀的地方。
还有更多的优点(参见 Joshua Bloch 的 Effective Java 2e),但这些是我发现与我目前所从事的工作最相关的几点。
[1] Java 语言中没有任何内容实际上提供了深度复制的默认结构。至多,对象只能告诉程序员,它们可以通过实现或提供复制构造函数来深度复制。Cloneable
与 Object.clone() 方法相比,复制构造函数为我们提供了许多优势,因为它们
- 不要强迫我们实现任何接口或抛出异常。
- 不需要任何演员表。
- 不要要求我们依赖未知对象创建机制。
- 不要要求父类遵循任何约定或实现任何内容。
- 允许我们修改最终字段。
- 允许我们完全控制对象的创建,我们可以在其中编写我们的初始化逻辑。
阅读有关 Java Cloning - Copy Constructor versus Cloning 的更多信息
通过复制构造函数,我们可以在不使用许多复杂的东西(例如实现可克隆接口和覆盖克隆方法)的情况下进行克隆。此外,我们无需特别担心深度克隆。
但需要注意的几点是:
1.当我们实现Cloneable时,这是对其他类/用户的暗示,即该类的对象是可克隆的。否则,其他类可能没有关于可克隆的显式信息。
2.如果我们将复制构造函数设为私有,那么我们可以限制克隆这个类的对象。然后,此复制构造函数只能用于初始化本地类中新创建的对象,而不是用于其他类中的克隆目的。
3.当你不想让你的类可克隆,但如果你写了带有访问说明符的复制构造函数,那么它会导致其他类可以创建你的类对象的不安全感。
复制构造函数实现了浅层和深度克隆机制,但与克隆相比,使用复制构造函数(使用可克隆接口)的主要优点是:
- 在使用 Object.clone() 方法时,我们不需要任何类型的大小写。
- 我们将能够修改最终字段以进行复制,这与在 Object.clone() 机制的情况下无法修改或访问最终字段不同。
- 它允许我们完全控制对象创建,我们可以在其中编写我们的初始化逻辑。
- 如果我们想克隆包含其他依赖类的引用变量的类的对象,我们不需要实现该类的克隆方法。只需初始化我们的复制构造函数,我们就可以实现这一点。
请考虑此示例,其中超类提供了一个复制构造函数,以隐式强制开发人员手动将字段复制到父类。这对于下投很有用:
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);
}
}
评论
employee.getRollNo()
employee.rollNo
employee.getName()
employee.name
get
set