前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 中的拷贝构造方法

Java 中的拷贝构造方法

作者头像
明明如月学长
发布2021-08-31 11:17:56
1.7K0
发布2021-08-31 11:17:56
举报
文章被收录于专栏:明明如月的技术专栏

译者注:https://www.baeldung.com/ 是一个文章质量非常高的英文技术网站,感兴趣的同学可以去访问学习。

1.介绍

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

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

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

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

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

代码语言:javascript
复制
public class Employee {
    private int id;
    private String name;
   
    public Employee(Employee employee) {
    }
}

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

代码语言:javascript
复制
public class Employee {
    private int id;
    private String name;
     
    public Employee(Employee employee) {
        this.id = employee.id;
        this.name = employee.name;
    }
}

上面的做法属于浅拷贝。

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

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

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

代码语言:javascript
复制
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的子类型和拷贝构造方法。

代码语言:javascript
复制
public class Manager extends Employee {
    private List<Employee> directReports;
    // ... 其他构造方法
 
    public Manager(Manager manager) {
        super(manager.id, manager.name, manager.startDate);
        this.directReports = directReports.stream()
          .collect(Collectors.toList());
    }
}

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

代码语言:javascript
复制
Employee source = new Manager(1, "Baeldung Manager", startDate, directReports);

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

代码语言:javascript
复制
Employee clone = new Manager((Manager) source);

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

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

代码语言:javascript
复制
public class Employee {
   public Employee copy() {
        return new Employee(this);
    }
}
 
public class Manager extends Employee {
    @Override
    public Employee copy() {
        return new Manager(this);
    }
}

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

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

代码语言:javascript
复制
Employee clone = source.copy();

5.结论

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/12/20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.介绍
  • 2.如何创造拷贝构造方法
  • 3.拷贝构造方法 VS Clone
  • 4.继承问题
  • 5.结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档