国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

從clone方法到復(fù)制構(gòu)造函數(shù)

孫吉亮 / 2431人閱讀

摘要:有一些設(shè)計缺陷,其中最大的一個是接口沒有方法。這基本上就是你用復(fù)制構(gòu)造函數(shù)做的事情。復(fù)制構(gòu)造方法有幾個優(yōu)點,我在本書中有討論。的方法是非常棘手的。它創(chuàng)建一個對象而不調(diào)用構(gòu)造函數(shù)。無法保證它保留構(gòu)造函數(shù)建立的不變量。

前言

在Java API中,可以通過實現(xiàn)Cloneable接口并重寫clone方法實現(xiàn)克隆,但Java設(shè)計者否定了使用clone創(chuàng)建新對象的方法.

1. clone方法實現(xiàn)對象的復(fù)制

在Java API中,如果被克隆的對象成員變量有對象變量,則對象變量也需要實現(xiàn)Cloneable接口,并重新給新的父類賦值,例如:

1.創(chuàng)建一個對象,其存在對象類型的成員變量childClone

class ParentsClone implements Cloneable {

    public int id;
    public ChildClone childClone;

    public ParentsClone(int id) {
        this.id = id;
    }

    public ParentsClone(int id, ChildClone childClone) {
        this.id = id;
        this.childClone = childClone;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

2.因此ChildClone也需要實現(xiàn)Cloneable:

class ChildClone implements Cloneable {
    public String name;

    public ChildClone(String name) {
        this.name = name;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

3.所以要做到真正的clone需要按照如下調(diào)用順序操作:

public class ParentClone implements Cloneable {

    public static void main(String[] args) throws CloneNotSupportedException {
        ParentsClone p1 = new ParentsClone(1, new ChildClone("HAHA"));
        ParentsClone p2 = (ParentsClone) p1.clone();
        p2.childClone = (ChildClone) p1.childClone.clone();

        System.out.println("p1 HashCode: " + p1.hashCode() + "  p1.child HashCode: " + p1.childClone.hashCode());
        System.out.println("p2 HashCode: " + p2.hashCode() + "  p2.child HashCode: " + p2.childClone.hashCode());
    }
}
//output:
/**
* p1 HashCode: 1163157884  p1.child HashCode: 1956725890
* p2 HashCode: 356573597  p2.child HashCode: 1735600054
*/

4.如此便完成了java對象的真正clone.但是java開發(fā)者并不建議這樣做.

2. 和JAVA開發(fā)者對話

Bill Venners: 在你的書中,你建議使用復(fù)制構(gòu)造函數(shù)而不是實現(xiàn)Cloneable和編寫clone。你能詳細說明嗎?

Josh Bloch:如果你已經(jīng)閱讀了我的書中關(guān)于克隆的章節(jié),特別是如果你看得仔細的話,你就會知道我認為克隆已經(jīng)完全壞掉的東西。有一些設(shè)計缺陷,其中最大的一個是 Cloneable 接口沒有 clone方法。這意味著它根本不起作用:實現(xiàn)了 Cloneable 接口并不說明你可以用它做什么。相反,它說明了內(nèi)部可能做些什么。它說如果通過super.clone 反復(fù)調(diào)用它最終調(diào)用 Object 的 clone 方法,這個方法將返回原始的屬性副本。

但它沒有說明你可以用一個實現(xiàn) Cloneable 接口的對象做什么,這意味著你不能做多態(tài) clone 操作。如果我有一個 Cloneable 數(shù)組,你會認為我可以運行該數(shù)組并克隆每個元素以制作數(shù)組的深層副本,但不能。你不能強制轉(zhuǎn)換對象為 Cloneable 接口并調(diào)用 clone 方法,因為 Cloneable 沒有public clone 方法,Object 類也沒有。如果您嘗試強制轉(zhuǎn)換 Cloneable 并調(diào)用該 clone 方法,編譯器會說您正在嘗試在對象上調(diào)用受保護的clone方法。

事實的真相是,您不通過實施 Cloneable 和提供 clone 除復(fù)制能力之外的公共方法為您的客戶提供任何能力。如果您提供具有不同名稱的copy操作, 怎么也不次于去實現(xiàn) Cloneable 接口。這基本上就是你用復(fù)制構(gòu)造函數(shù)做的事情。復(fù)制構(gòu)造方法有幾個優(yōu)點,我在本書中有討論。一個很大的優(yōu)點是可以使副本具有與原始副本不同的實現(xiàn)。例如,您可以將一個 LinkedList 復(fù)制到 ArrayList。

Object 的 clone 方法是非常棘手的。它基于屬性復(fù)制,而且是“超語言”。它創(chuàng)建一個對象而不調(diào)用構(gòu)造函數(shù)。無法保證它保留構(gòu)造函數(shù)建立的不變量。多年來,在Sun內(nèi)外存在許多錯誤,這源于這樣一個事實,即如果你只是super.clone 反復(fù)調(diào)用鏈直到你克隆了一個對象,那么你就擁有了一個淺層的對象副本。克隆通常與正在克隆的對象共享狀態(tài)。如果該狀態(tài)是可變的,則您沒有兩個獨立的對象。如果您修改一個,另一個也會更改。突然之間,你會得到隨機行為。

我使用的東西很少實現(xiàn) Cloneable。我經(jīng)常提供實現(xiàn)類的 clone 公共方法,僅是因為人們期望有。我沒有抽象類實現(xiàn) Cloneable,也沒有接口擴展它,因為我不會將實現(xiàn)的負擔(dān) Cloneable 放在擴展(或?qū)崿F(xiàn))抽象類(或接口)的所有類上。這是一個真正的負擔(dān),幾乎沒有什么好處。

Doug Lea 走得更遠。他告訴我 clone 除了復(fù)制數(shù)組之外他不再使用了。您應(yīng)該使用 clone 復(fù)制數(shù)組,因為這通常是最快的方法。但 Doug 的類根本就不再實施 Cloneable了。他放棄了。而且我認為這并非不合理。

這是一個恥辱, Cloneable 接口壞掉了,但它發(fā)生了。最初的 Java API在緊迫的期限內(nèi)完成,以滿足市場窗口收緊的需求。最初的 Java 團隊做了不可思議的工作,但并非所有的 API 都是完美的。 Cloneable 是一個弱點,我認為人們應(yīng)該意識到它的局限性。
傳送門:<復(fù)制構(gòu)造函數(shù)與克隆>英文原版

3. 總結(jié)Java開發(fā)者的話

設(shè)計缺陷, Cloneable 接口沒有 clone方法.

調(diào)用的是Object的clone方法,返回原始的屬性副本.

clone方法返回淺層的對象副本.

應(yīng)該使用 clone 復(fù)制數(shù),因為通常速度最快..{具體使用: int[] newArrays=(int[])oldArrays.clone() }

復(fù)制構(gòu)造方法的優(yōu)點:副本具有與原始副本不同的實現(xiàn).

4. 復(fù)制構(gòu)造函數(shù)

java開發(fā)者不建議我們使用clone方法,從而轉(zhuǎn)向靈活的構(gòu)造函數(shù)實現(xiàn)方法.
1.新寫兩個類,分別兩個構(gòu)造函數(shù),關(guān)注第二個構(gòu)造函數(shù),參數(shù)為當(dāng)前類的對象實例.

class Parents {

    public int id;
    public Child child;

    public Parents(int id, Child child) {
        this.id = id;
        this.child = child;
    }
    //實現(xiàn)對象的復(fù)制
    public Parents(Parents parents) {
        id = parents.id;
        child = new Child(parents.child);
    }
}


class Child {
    public String name;

    public Child(String name) {
        this.name = name;
    }
    //實現(xiàn)對象的復(fù)制
    public Child(Child child) {
        name = child.name;
    }
}

2.測試:

public static void main(String[] args) throws CloneNotSupportedException {

       Parents p1=new Parents(1,new Child("HAHA"));
       Parents p2=new Parents(p1);

       System.out.println("p1 HashCode: " + p1.hashCode() + "  p1.child HashCode: " + p1.child.hashCode());
       System.out.println("p2 HashCode: " + p2.hashCode() + "  p2.child HashCode: " + p2.child.hashCode());

       //output
       /**
        * p1 HashCode: 1163157884  p1.child HashCode: 1956725890
        * p2 HashCode: 356573597  p2.child HashCode: 1735600054
        */

   }
結(jié)語

以上便是筆者對放棄clone,使用構(gòu)造方法創(chuàng)建新對象的整理.以后的程序中盡量還是多用復(fù)制構(gòu)造函數(shù)的方法.若有不足,敬請指正.

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/73949.html

相關(guān)文章

  • Java 作者談克隆方法的實現(xiàn)

    摘要:不合規(guī)的代碼示例合規(guī)解決方案參閱復(fù)制構(gòu)造函數(shù)與克隆也可以參閱應(yīng)該實現(xiàn)克隆覆蓋的類應(yīng)為并調(diào)用下面為引文翻譯談設(shè)計與作者的對話,作者首次在上發(fā)表,年月日復(fù)制構(gòu)造函數(shù)與克隆在你的書中,你建議使用復(fù)制構(gòu)造函數(shù)而不是實現(xiàn)和編寫。 今天在用 sonar 審核代碼, 偶然看到下面的提示:showImg(https://segmentfault.com/img/bVbqioZ?w=858&h=116)...

    gaomysion 評論0 收藏0
  • [譯] 為什么原型繼承很重要

    摘要:使用構(gòu)造函數(shù)的原型繼承相比使用原型的原型繼承更加復(fù)雜,我們先看看使用原型的原型繼承上面的代碼很容易理解。相反的,使用構(gòu)造函數(shù)的原型繼承像下面這樣當(dāng)然,構(gòu)造函數(shù)的方式更簡單。 五天之前我寫了一個關(guān)于ES6標(biāo)準(zhǔn)中Class的文章。在里面我介紹了如何用現(xiàn)有的Javascript來模擬類并且介紹了ES6中類的用法,其實它只是一個語法糖。感謝Om Shakar以及Javascript Room中...

    xiao7cn 評論0 收藏0
  • 搞定PHP面試 - PHP魔術(shù)方法知識點整理

    摘要:魔術(shù)方法知識點整理代碼使用語法編寫一構(gòu)造函數(shù)和析構(gòu)函數(shù)構(gòu)造函數(shù)具有構(gòu)造函數(shù)的類會在每次創(chuàng)建新對象時先調(diào)用此方法,所以非常適合在使用對象之前做一些初始化工作。在析構(gòu)函數(shù)中調(diào)用將會中止其余關(guān)閉操作的運行。析構(gòu)函數(shù)中拋異常會導(dǎo)致致命錯誤。 PHP魔術(shù)方法知識點整理 代碼使用PHP7.2語法編寫 一、構(gòu)造函數(shù)和析構(gòu)函數(shù) __construct() 構(gòu)造函數(shù) __construct ([ mi...

    付永剛 評論0 收藏0
  • 設(shè)計模式之原型模式

    摘要:但是這種復(fù)制技術(shù)在的世界里早已出現(xiàn),就是原型模式什么是原型模式用原型實例指定創(chuàng)建對象的種類,并且通過拷貝這些原型創(chuàng)建新的對象類圖原型模式是設(shè)計模式中最簡單的,沒有之一。 前言 在現(xiàn)實世界中,我們通常會感覺到分身乏術(shù)。要是自己有分身那該多好啊,一個用來工作,一個用來看電視,一個用來玩游戲(無意中透露了自己單身狗的身份-。-),其實就是克隆,這種技術(shù)存在著很大的弊端,所以現(xiàn)在是禁止使用的。...

    jsyzchen 評論0 收藏0
  • JavaScript 原型鏈

    摘要:命令通過構(gòu)造函數(shù)新建實例對象,實質(zhì)就是將實例對象的原型,指向構(gòu)造函數(shù)的屬性,然后在實例對象上執(zhí)行構(gòu)造函數(shù)。 大部分面向?qū)ο蟮木幊陶Z言,都是以類(class)作為對象體系的語法基礎(chǔ)。JavaScript語言中是沒有class的概念的(ES6之前,ES6中雖然提供了class的寫法,但實現(xiàn)原理并不是傳統(tǒng)的類class概念,僅僅是一種寫法), 但是它依舊可以實現(xiàn)面向?qū)ο蟮木幊蹋@就是通過Ja...

    verano 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<