首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 複製建構子缺陷分析:為何 C++ 模式在 Java 失效

     編輯:Java 相關知識

複製建構子是 C++ 基礎機制,可自動產生本地副本。但在 Java 並不適用。以下範例展示完整複製建構子實作與其失效場景:

//: CopyConstructor.java
class FruitQualities { /* ... 複製建構子複製所有欄位 ... */ }
class Seed { /* ... 複製建構子 ... */ }
class Fruit {
    private FruitQualities fq;
    private int seeds;
    private Seed[] s;
    Fruit(FruitQualities q, int seedCount) { /* ... */ }
    // 複製建構子:深層複製 fq 與每個 Seed
    Fruit(Fruit f) {
        fq = new FruitQualities(f.fq);
        seeds = f.seeds;
        for(int i = 0; i < seeds; i++)
            s[i] = new Seed(f.s[i]);
    }
    protected void addQualities(FruitQualities q) { fq = q; }
    protected FruitQualities getQualities() { return fq; }
}
class Tomato extends Fruit {
    Tomato() { super(new FruitQualities(), 100); }
    Tomato(Tomato t) { super(t); /* ... */ }
}
class ZebraQualities extends FruitQualities { /* ... */ }
class GreenZebra extends Tomato {
    GreenZebra() { addQualities(new ZebraQualities()); }
    GreenZebra(GreenZebra g) {
        super(g); // 呼叫 Tomato(Tomato)
        addQualities(new ZebraQualities()); // 恢復正確品質
    }
    void evaluate() {
        ZebraQualities zq = (ZebraQualities)getQualities();
        // ...
    }
}
public class CopyConstructor {
    static void ripen(Tomato t) {
        t = new Tomato(t); // 使用複製建構子
        System.out.println("In ripen, t is a " + t.getClass().getName());
    }
    static void slice(Fruit f) {
        f = new Fruit(f); // 嘗試複製
        System.out.println("In slice, f is a " + f.getClass().getName());
    }
    public static void main(String[] args) {
        Tomato tomato = new Tomato();
        ripen(tomato); // OK
        slice(tomato); // OOPS!
        GreenZebra g = new GreenZebra();
        ripen(g); // OOPS!
        slice(g); // OOPS!
        g.evaluate();
    }
} ///:~

輸出結果揭示核心問題

In ripen, t is a Tomato
In slice, f is a Fruit
In ripen, t is a Tomato
In slice, f is a Fruit

slice() 接收 Fruit 參數並用 Fruit 複製建構子複製,導致 Tomato 或 GreenZebra 特有特徵遺失——物件被「切割」為基類型。ripen() 雖能正確複製 Tomato,但面對 GreenZebra 仍退化為 Tomato。

為何 C++ 適用而 Java 不行?

C++ 可直接傳遞物件(by value),複製建構子自動觸發。Java 一切皆參考(handle),無 by value 機制。C++ 複製建構子配合 by value 參數傳遞完美運作;Java 無此語意基礎,強行模仿反而破壞多型。

結論:Java 中不要使用複製建構子製作本地副本。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved