1.介绍

Java 中的拷贝构造方法是一种使用该类的一个对象构造另外一个对象的构造方法。

当需要拷贝一个带有多个成员变量的复杂对象或者想构造已存在对象的深拷贝对象时非常有用。

译者注:本文内容很简单,但是很实用。拷贝构造方法实战中用虽然用的不多,但是是一个非常不错的技巧。

2.如何创造拷贝构造方法

要创建拷贝构造方法,首先需要声明带有和本类相同类型的参数构造函数:

public class Employee {

private int id;

private String name;

public Employee(Employee employee) {

}

}

然后,将参数对象的每个属性都复制给新的实例。

public class Employee {

private int id;

private String name;

public Employee(Employee employee) {

this.id = employee.id;

this.name = employee.name;

}

}

上面的做法属于浅拷贝。

上面定义的属性不是int 就是 String, 只包含基本类型和不可变类型,因此使用前拷贝就没问题。

但是如果类中包含可变类型就要通过该构造函数实现深拷贝。

为了实现深拷贝,我们需要根据原始可变对象类型构造新的实例。

public class Employee {

private int id;

private String name;

private Date startDate;

public Employee(Employee employee) {

this.id = employee.id;

this.name = employee.name;

this.startDate = new Date(employee.startDate.getTime());

}

}

3.拷贝构造方法 VS Clone

在 Java 中,我们还可以使用 clone 方法实现根据已有对象创建新对象。

但是拷贝构造方法更有优势:

拷贝构造方法实现更简单。不需要实现 Cloneable 接口,也不需要处理 CloneNotSupportedException

clone 函数返回一个普通的 Object 类型的引用。还需要转成特定的类型。

在 clone 方法中不能为 final 属性赋值,但是在拷贝构造方法中就可以。

4.继承问题

Java 中的拷贝构造方法不会被子类继承。

因此,如果我们尝试初始化一个带有父类引用的子类对象,就会面临着类型转换问题。

为了更好地说明这个问题,我们首先创建 Employee的子类型和拷贝构造方法。

public class Manager extends Employee {

private List directReports;

// ... 其他构造方法

public Manager(Manager manager) {

super(manager.id, manager.name, manager.startDate);

this.directReports = directReports.stream()

.collect(Collectors.toList());

}

}

然后,我们声明一个 Employee 类型的引用指向通过 Manager 构造方法构造的 Manager 实例。

Employee source = new Manager(1, "Baeldung Manager", startDate, directReports);

由于引用类型为 Employee, 如果我们想使用 Manager 的拷贝构造函数就必须将 source 强转为 Manager 类型。

Employee clone = new Manager((Manager) source);

如果参数不是 Manager 类型,运行时会抛出 ClassCastException。

其中一种避免使用拷贝构造方法时类型转换的方法是创建一个继承的拷贝函数:

public class Employee {

public Employee copy() {

return new Employee(this);

}

}

public class Manager extends Employee {

@Override

public Employee copy() {

return new Manager(this);

}

}

在每个类的拷贝函数中调用自己类型的拷贝构造函数即可。

这样就保证了生成的对象和调用的对象类型相同。

Employee clone = source.copy();

5.结论

本文介绍了拷贝构造方法,给出了避免使用 clone 函数的原因。

如果引用类型为父类型而实际对象类型为子类型时,使用子类型的拷贝构造函数需要将父类型强制类型转换为子类型,容易出现转换问题。本文也针对这个问题提供了解决方案。

如果你觉得本文对你有帮助,欢迎点赞、转发、评论,你的支持是我创作的最大动力。

另外想学习,更多开发和避坑技巧,少走弯路,请关注我的专栏:《阿里巴巴Java 开发手册》详解专栏

复制构造函数java_Java中的拷贝构造函数相关推荐

  1. C++学习笔记day47-----C++98-继承中的构造函数,析构函数,拷贝构造函数,拷贝赋值函数,多重继承,虚继承

    继承中的构造函数 当通过一个子类创建一个新的对象时,编译器会根据子类在初始化表中指明的基类的初始化方式去调用基类相应的构造函数.如果子类的初始化表中,并没有指明基类的初始化方式,编译器将会调用基类的无 ...

  2. C++类中的拷贝构造函数

    文章目录 前言 二.拷贝构造函数 1.拷贝构造函数定义 2.默认拷贝构造函数存在的问题 3.解决方式 三 总结 四 参考 如有错误,希望大家批评指正,日拱一卒,功不唐捐. 前言 最近项目的技术栈是C+ ...

  3. 继承关系中的拷贝构造函数和赋值操作重载函数分析

    文章目录 1 继承关系中的拷贝构造函数和赋值操作重载函数分析 1 继承关系中的拷贝构造函数和赋值操作重载函数分析 在继承关系中,如果子类未实现拷贝构造函数,那么在子类进行拷贝构造操作时,会直接调用父类 ...

  4. C++ 笔记(17)— 类和对象(构造函数、析构函数、拷贝构造函数)

    1. 构造函数 构造函数是一种特殊的函数(方法),在根据类创建对象时被调用.构造函数是一种随着对象创建而自动被调用的函数,它的主要用途是为对象作初始化. 构造函数的名称与类的名称是完全相同的,并且不会 ...

  5. C++入门:构造函数,析构函数,拷贝构造函数,运算符重载详解

    目录 类的6个默认成员函数 一.构造函数 1.概念 2.特征如下: (1) 函数名与类名相同. (2)无返回值. (3)对象实例化时编译器自动调用对应的构造函数. (4)构造函数可以重载. (5)如果 ...

  6. C++ 类和对象(二):构造函数、析构函数、拷贝构造函数、运算符重载

    构造函数 析构函数 拷贝构造函数 运算符重载 class Date {}; 可以看到,上面那个类没有任何成员,是一个空类,但是它真的什么都没有吗?其实一个类在我们不写的情况下,都会生成6个默认的成员函 ...

  7. 类的6个默认成员函数:构造函数、析构函数、拷贝构造函数、重载运算符、三/五法则

    文章目录 6个默认成员函数 构造函数 概念 默认构造函数的类型 默认实参 概念 默认实参的使用 默认实参声明 全局变量作为默认实参 某些类不能依赖于编译器合成的默认构造函数 第一个原因 第二个原因 第 ...

  8. 【C++】C++类的学习(二)——构造函数、析构函数、拷贝构造函数以及this指针

    [fishing-pan:https://blog.csdn.net/u013921430转载请注明出处] 1. 前言 在之前的博文< C++类的学习(一)--初识类>中,简单地讲述了类的 ...

  9. 类与对象:类的6个默认成员函数: 构造函数、析构函数、拷贝构造函数、赋值操作符重载、默认拷贝构造与赋值运算符重载的问题、const成员函数、 取地址及const取地址操作符重载

    1.类的6个默认成员函数 如果一个类中什么成员都没有,简称为空类.任何一个类在我们不写的情况下,都会自动生成下面6个默认成员函数. 构造函数 析构函数 拷贝构造函数 赋值操作符重载 const成员函数 ...

最新文章

  1. RH134 UNIT5
  2. AlphaFold和RoseTTAFold双剑合璧,成功预测蛋白质复合体结构,北大校友领衔登上Science...
  3. python3 logging 句柄释放 shutdown 简介
  4. java的query_Java-Query
  5. C++ Primer 5th笔记(chap 18 大型程序工具) using指示
  6. POSIX文件及目录管理
  7. leetcode96. 不同的二叉搜索树(动态规划)
  8. java取余数的函数_左神算法基础:哈希函数和哈希表
  9. css hack *html,HTML_CSS Hack整理,CSS Hack是在标准CSS没办法兼容 - phpStudy
  10. 2021-2025年中国一氧化碳烟雾报警器行业市场供需与战略研究报告
  11. pattern recognition letter 投稿时word 模板的说明乱码
  12. 开启win7笔记本自带无线功能
  13. 迷你世界显示服务器错误,迷你世界登陆失败怎么办-迷你世界登陆未成功_牛游戏页游...
  14. python写酒店管理系统_基于WEB的小型酒店管理系统,源码下载
  15. CSDN使用MD编辑器写博客如何让图片居中(调整图片位置大小)MD编辑器学习笔记
  16. Qt撤销回/撤框架:QUndoCommand
  17. 【数据安全案例】案例汇总
  18. 没有权限访问网络资源/Windows7虚拟机共享文件
  19. 3.找回原来win10右键的方法
  20. 央视新闻30分:开心网流行背后存在的隐忧

热门文章

  1. Android音乐播放器(二)登录注册界面
  2. 两个卡方分布之和_推荐基础算法之矩阵分解PFM
  3. 【数据库】DBMS几种进程模型优劣与举例
  4. 禁用某盾加密破解、黄盾加密、sdhelper2.exe
  5. 100页PPT,带你了解数字化、智能化车间规划与建设!
  6. 移动端适配+flexible.js+rem适配
  7. Jsp格式化显示Date类型数据
  8. 基于微信平台做视频直播时,如何裂变引流吸粉
  9. android开发皮肤检测,android – 检测皮肤和捕获图像
  10. 2019年各大互联网公司端午节礼盒指南