You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不借助Cloneable/arraycopy及显式类型转换,用拷贝构造函数深拷贝对象数组?

问题解答

核心结论

  1. 可以调用对象的拷贝构造函数,但不能用你当前这种父类构造硬转的方式,得靠多态让子类自己暴露拷贝能力。
  2. 现有代码必须修改,当前写法本质是把所有子类对象降级成父类实例拷贝,完全丢失子类属性和行为,且硬转+异常捕获的方式既丑陋又不可扩展。
  3. 多态完全支持这个场景,通过父类定义抽象拷贝接口,子类实现具体逻辑,就能在运行时自动匹配对应子类的拷贝行为,无需显式类型转换。

具体修改方案

1. 重构父类Building,定义抽象拷贝方法

把Building改成抽象类,新增一个copy()抽象方法,强制所有子类实现自己的拷贝逻辑:

public abstract class Building {
    protected int windows;
    protected boolean basement;

    // 供子类调用的基础构造
    protected Building(int windows, boolean basement) {
        this.windows = windows;
        this.basement = basement;
    }

    // 抽象拷贝方法,子类需实现
    public abstract Building copy();
}

2. 子类实现拷贝构造和copy()方法

每个子类编写自己的拷贝构造函数,并在copy()方法中调用该构造返回子类实例:
以House为例:

public class House extends Building {
    private boolean hasGarage; // 子类特有属性

    // 普通构造
    public House(int windows, boolean basement, boolean hasGarage) {
        super(windows, basement);
        this.hasGarage = hasGarage;
    }

    // 子类拷贝构造函数
    public House(House other) {
        super(other.windows, other.basement);
        this.hasGarage = other.hasGarage;
    }

    // 实现父类拷贝方法
    @Override
    public Building copy() {
        return new House(this);
    }
}

另一个子类Apartment同理:

public class Apartment extends Building {
    private int floor; // 子类特有属性

    public Apartment(int windows, boolean basement, int floor) {
        super(windows, basement);
        this.floor = floor;
    }

    public Apartment(Apartment other) {
        super(other.windows, other.basement);
        this.floor = other.floor;
    }

    @Override
    public Building copy() {
        return new Apartment(this);
    }
}

3. 修改数组拷贝方法

直接调用每个对象的copy()方法,依赖多态自动触发对应子类的拷贝逻辑:

public static Building[] copyBuildings(Building[] objects) {
    Building[] objList = new Building[objects.length];
    for (int i = 0; i < objects.length; i++) {
        objList[i] = objects[i].copy();
    }
    return objList;
}

方案优势

  • 完全规避显式类型转换:子类自己处理拷贝逻辑,父类只提供统一接口。
  • 多态生效:运行时JVM会根据对象实际类型调用对应的copy()方法,返回正确的子类实例,不会丢失子类属性。
  • 可扩展性强:新增子类时,只需要实现拷贝构造和copy()方法即可,无需修改父类或数组拷贝逻辑。

原代码问题分析

你原来的Building(Object obj)构造函数通过捕获ClassCastException来适配不同子类,这种方式存在致命问题:

  • 所有拷贝出的对象都是Building类型,子类特有的属性会丢失。
  • 新增子类时,必须在父类构造中新增对应的try-catch块,违反开闭原则。
  • 代码可读性差,硬转的逻辑容易出错。

内容的提问来源于stack exchange,提问作者Gray

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 17:33:06