使可變性最小

第十五條:使可變性最小


1.什么是不可變類刹帕?

(1)需要的所有參數(shù)必須在實(shí)例化的時(shí)候都傳進(jìn)去。
(2)對(duì)象中所有信息在對(duì)象的整個(gè)生命周期中都保持不變管挟。

2.使類不可變的原則

(1)不要提供任何修改對(duì)象狀態(tài)的方法。
(2)保證類不會(huì)被繼承弄捕。
(3)使所有的域都是final類型的。
(4)使所有的域都是私有類型的够滑。
(5)確保對(duì)于任何可變組件的互斥性蛤高。意思就是蚣旱,確保在該類的外部不會(huì)獲取到該類中可變對(duì)象的引用。比如下面這個(gè)例子:

public class MyObject{
  private final List<String> list = new ArrayList<>;//可變對(duì)象
  public List<String> getList() {
    return new ArrayList(list);
  }
  public void setList(List<String> list) {
    this.list = new ArrayList(list);
  }
}

3.不可變類的優(yōu)點(diǎn)

(1)不可變類簡(jiǎn)單戴陡。
不可變類只有一種狀態(tài)塞绿,就是它被創(chuàng)建出來時(shí)候的狀態(tài),如果你要根據(jù)這個(gè)類進(jìn)行一系列復(fù)雜操作猜欺,那么這個(gè)操作無論在什么時(shí)候結(jié)果都是相同的位隶,所以你可以直接將結(jié)果緩存起來拷窜,在下一次執(zhí)行同樣操作的時(shí)候取出來开皿,而不必再進(jìn)行下一次操作。
(2)不可變類本質(zhì)上是線程安全的篮昧,它不需要同步鎖赋荆。
(3)對(duì)于不可變類,你永遠(yuǎn)都不需要實(shí)現(xiàn)拷貝方法懊昨。拷貝方法對(duì)它來說是沒有意義的窄潭。
(4)不可變類可以被自由的共享。

4.不可變對(duì)象的缺點(diǎn)

(1)對(duì)于每一個(gè)不同的值都需要?jiǎng)?chuàng)建一個(gè)新的對(duì)象酵颁。

5.缺點(diǎn)的彌補(bǔ)辦法

(1)先猜測(cè)一下經(jīng)常用到哪些多步驟的操作嫉你,然后將它們作為基本數(shù)據(jù)類型提供。比如Integer,它將值為-128到127的對(duì)象緩存起來躏惋,但調(diào)用valueOf(int i)的時(shí)候幽污,直接從緩存中拿,不用再重復(fù)創(chuàng)建提高效率簿姨。

(2)我們可以創(chuàng)建一個(gè)可變配套類距误。例如String是一個(gè)不可變類簸搞,它的可變配套類為StirngBuilder和StringBuffer。下面是一個(gè)例子准潭,我們現(xiàn)在實(shí)現(xiàn)一個(gè)復(fù)數(shù)類趁俊,對(duì)外提供一個(gè)相加的方法如下:

public class Complex {
  private final double re;//實(shí)部
  private final double im;//虛部

  private Complex(double re, double im) {
    this.re = re;
    this.im = im;
  }

  public static Complex valueOf(double re, double im) {
    return new Complex(re, im);
  }

  public double realPart() {
    return re;
  }
  public double imaginaryPart() {
    return im;
  }
  
  //復(fù)數(shù)相加
  public Complex add(Complex c) {
    return new Complex(re + c.re, im + c.im);
  }
}

我們可以為他創(chuàng)建一個(gè)配套類:

public class ComplexBuilder {
  private double re;
  private double im;
  
  private ComplexBuider(double re, double im) {
    this.re = re;
    this.im = im;
  }
  public static ComplexBuider newInstance(Complex c) {
    return new ComplexBuilder(c.realPart(), c.imaginaryPart());
  }

  public void add(Complex c) {
    this.re = this.re + c.realPart();
    this.im = this.im + c.imaginaryPart();
  }

  public Complex toComplex() {
    return Complex.valueOf(this.re, this.im);
  }
}

在客戶端中我們?nèi)绻枰靡粋€(gè)復(fù)數(shù)和另一個(gè)復(fù)數(shù)相加100次,我們?nèi)绻挥肅omplexBuilder的話就像下面這樣刑然,算上最開始穿件的兩個(gè)實(shí)例寺擂,我們將會(huì)創(chuàng)建102個(gè)實(shí)例:

public class Test {
  @Test
  public void addNoBuiderTest() throws Exception{
    Complex c1 = Complex.valueOf(1, 2);
    Complex c2 = Complex.valueOf(2, 3);
    for (int i = 0 ; i < 100 ; i++) {
      c1 = c1.add(c2);
    }
  }
}

現(xiàn)在改用ComplexBuilder,現(xiàn)在我們只會(huì)創(chuàng)建4個(gè)實(shí)例:

public class Test {
  @Test
  public void addNoBuiderTest() throws Exception{
    Complex c1 = Complex.valueOf(1, 2);
    Complex c2 = Complex.valueOf(2, 3);
    ComplexBuilder cb = ComplexBuider.newInstance(c1);
    for (int i = 0 ; i < 100 ; i++) {
      cb.add(c2);
    }
    c1 = cb.toComplex();
  }
}

6.總結(jié)

(1)堅(jiān)決不要為每個(gè)getter都生成setter闰集。
(2)能將類做成不可變的就做成不可變的沽讹。
(3)一般比較小的值類都是需要做成不可變的。
(4)對(duì)于一些比較大的值類盡量考慮實(shí)現(xiàn)成不可變類武鲁。
(5)性能方面很有必要的時(shí)候才需提供配套類爽雄。
(6)如果真的不能作為不可變類,那就盡量限制其可變性
(7)對(duì)于一個(gè)類的初始化只能在構(gòu)造器或是靜態(tài)工廠中完成沐鼠。也就是說類的初始化操作(賦值之類的)只能執(zhí)行一次挚瘟,就是在構(gòu)造器或是靜態(tài)工廠中。這一點(diǎn)參考java類庫中的TimerTask類饲梭。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乘盖,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子憔涉,更是在濱河造成了極大的恐慌订框,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兜叨,死亡現(xiàn)場(chǎng)離奇詭異穿扳,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)国旷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門矛物,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人跪但,你說我怎么就攤上這事履羞。” “怎么了屡久?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵忆首,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我被环,道長(zhǎng)糙及,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任蛤售,我火速辦了婚禮丁鹉,結(jié)果婚禮上妒潭,老公的妹妹穿的比我還像新娘。我一直安慰自己揣钦,他們只是感情好雳灾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著冯凹,像睡著了一般谎亩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宇姚,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天匈庭,我揣著相機(jī)與錄音,去河邊找鬼浑劳。 笑死阱持,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的魔熏。 我是一名探鬼主播衷咽,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蒜绽!你這毒婦竟也來了镶骗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤躲雅,失蹤者是張志新(化名)和其女友劉穎鼎姊,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體相赁,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡相寇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了噪生。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片裆赵。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡东囚,死狀恐怖跺嗽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情页藻,我是刑警寧澤桨嫁,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站份帐,受9級(jí)特大地震影響璃吧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜废境,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一畜挨、第九天 我趴在偏房一處隱蔽的房頂上張望筒繁。 院中可真熱鬧,春花似錦巴元、人聲如沸毡咏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呕缭。三九已至,卻和暖如春修己,著一層夾襖步出監(jiān)牢的瞬間恢总,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工睬愤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留片仿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓尤辱,卻偏偏與公主長(zhǎng)得像滋戳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子啥刻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 不可變類是指:其實(shí)例不能被修改的類奸鸯。每個(gè)實(shí)例中包含的所有信息都必須在創(chuàng)建該實(shí)例的時(shí)候就提供,并在對(duì)象的整個(gè)生命周期...
    慧執(zhí)行閱讀 599評(píng)論 0 0
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,180評(píng)論 25 707
  • 目錄 第二章 創(chuàng)建和銷毀對(duì)象 1 考慮用靜態(tài)工廠方法替代構(gòu)造器 對(duì)于代碼來說, 清晰和簡(jiǎn)潔是最重要的. 代碼應(yīng)該被...
    高廣超閱讀 1,452評(píng)論 0 12
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法可帽,類相關(guān)的語法娄涩,內(nèi)部類的語法,繼承相關(guān)的語法映跟,異常的語法蓄拣,線程的語...
    子非魚_t_閱讀 31,643評(píng)論 18 399
  • 公元1085年二月,宋神宗趙頊駕崩努隙,其年僅十歲的兒子趙煦即位球恤,即宋哲宗。由于年幼荸镊,由神宗母親宣仁高太后垂簾聽政咽斧。高...
    青年小圣閱讀 289評(píng)論 0 3