第八章、通用程序設(shè)計(jì)(一)

第四十五條、將局部變量的作用域最小化

  1. 將局部變量的作用最小化,可以增強(qiáng)代碼的可讀性和可維護(hù)性,并降低出錯(cuò)的可能性。異于C語言要求局部變量必須要在一個(gè)代碼塊的開頭處進(jìn)行聲明,Java允許在任何可以出現(xiàn)語句的地方聲明變量

  2. 最有力的方法是在第一次使用它的地方聲明。過早地聲明局部變量不僅會(huì)使它的作用域過早地?cái)U(kuò)展,而且結(jié)束地過晚了。局部變量的作用域從它被聲明的點(diǎn)開始拓展,一直到外圍塊的結(jié)束處。

  3. 幾乎每個(gè)局部變量的聲明都應(yīng)該包含一個(gè)初始表達(dá)式。如果你還沒有足夠的信息來對一個(gè)變量進(jìn)行有意義的初始化,就應(yīng)該推遲這個(gè)聲明,直到可以初始化為止。(有個(gè)例外是try-catch語句有關(guān),變量被一個(gè)方法初始化,而這個(gè)方法可能會(huì)拋出一個(gè)checked exception,則該變量必須在try的內(nèi)部被初始化。)

  4. 循環(huán)中提供了特殊的機(jī)會(huì)來將變量的作用域最小化。for循環(huán)都允許聲明循環(huán)變量(loop variable),它的作用域被限定在正好需要的范圍內(nèi):循環(huán)體、循環(huán)體之前的初始化、測試、更新部分。所以,如果在循環(huán)終止后不再需要循環(huán)變量的內(nèi)容,for循環(huán)就優(yōu)先于while循環(huán)。for循環(huán)相較于while循環(huán)的另一個(gè)優(yōu)勢在于:更簡短,從而增加了可讀性。


第四十六條、for-each循環(huán)優(yōu)先于傳統(tǒng)的for循環(huán)

  1. 在Java1.5之前,對集合進(jìn)行遍歷的首選做法:

     for(Iterator i = c.iterator();i.hasNext();){
         doSomething((Element)i.next());
     }
    

    對數(shù)組進(jìn)行遍歷的首選做法:

     for(int i = 0 ; i < a.length ; i++){
         doSomething(a[i]);
     }
    

    但是它們并不完美:迭代器和索引變量都會(huì)造成一些混亂,也代表著出錯(cuò)的可能。
    Java1.5 引入for-each循環(huán),通過完全隱藏迭代器或者索引變量,避免了混亂和出錯(cuò)的可能:

     for(Element e:elements){
         doSomething(e);
     }
    

    冒號代表在。。。里面,可以讀作對于元素elements中的每個(gè)元素e。這個(gè)在性能上可能還稍有優(yōu)勢。

  2. 在對多個(gè)集合進(jìn)行嵌套式迭代的時(shí)候,for-each循環(huán)的優(yōu)勢更加明顯。
    for-each循環(huán)不僅讓你遍歷集合和數(shù)組,還讓你遍歷任何實(shí)現(xiàn)Iterable接口的對象。這個(gè)簡單的接口由單個(gè)方法組成:

     public interface Iterable<E>{
         Iterator<E> iterator();
     }
    
  3. 有三種情況下無法使用for-each循環(huán):

    • 過濾:如果需要遍歷集合,并刪除選定的元素,就需要使用顯式的迭代器,以便可以調(diào)用它的remove方法;
    • 轉(zhuǎn)換:如果需要遍歷列表或者數(shù)組,并取代他部分或者全部的元素值,就需要列表迭代器或者數(shù)組索引,以便設(shè)定元素的值;
    • 平行迭代:如果需要并行地遍歷多個(gè)集合,就需要顯式地控制迭代器或者索引變量,以便所有的迭代器或者索引變量都可以同步前移。

第四十七條、了解和使用類庫

  1. 通過使用標(biāo)準(zhǔn)類庫,可以充分利用這些編寫標(biāo)準(zhǔn)類庫的專家的知識,以及在你之前的其他人的使用經(jīng)驗(yàn)。而且不必浪費(fèi)時(shí)間為那些與工作不太相關(guān)的問題提供特別的解決方案。而且它們的性能往往隨著時(shí)間的推移而不斷提高。可以使自己的代碼融入主流。

  2. 每個(gè)Java程序員應(yīng)該熟悉java.langjava.util還有java.io中的內(nèi)容,關(guān)于其他類庫的知識可以隨時(shí)學(xué)習(xí)。

  3. 兩個(gè)工具:

    • Collection Framework(集合框架)被加入到j(luò)ava.util包中,是一個(gè)統(tǒng)一的體系結(jié)構(gòu),用來表示和操作集合,允許它們對集合進(jìn)行獨(dú)立于表示細(xì)節(jié)的操作,從而減輕了編程的負(fù)擔(dān)且提高了效率和性能。
    • java.util.concurrent 包中有一組并發(fā)實(shí)用工具,既包含高級的并發(fā)工具來簡化多線程的編程任務(wù),還包含低級別的并發(fā)基本類型,允許專家們自己編寫更高級的并發(fā)抽象。

第四十八條、如果需要精確的答案,請避免使用float和double

  1. float和double類型主要是為了科學(xué)計(jì)算和工程計(jì)算而設(shè)計(jì)的。它們執(zhí)行二進(jìn)制浮點(diǎn)運(yùn)算,這是為了在廣泛的數(shù)值范圍上提供較為精確的快速近似計(jì)算而精心設(shè)計(jì)的。然而,它們并沒有提供完全精確的結(jié)果。尤其不適用于貨幣計(jì)算,讓float和double精確地表示0.1是不可能的。

  2. 使用BigDecimal、int或者long進(jìn)行貨幣計(jì)算:如果想讓系統(tǒng)來記錄十進(jìn)制小數(shù)點(diǎn),且不介意一絲不方便,請使用BigDecimal;如果性能特別關(guān)鍵,而且又不介意自己記錄十進(jìn)制的小數(shù)點(diǎn),涉及的數(shù)值不是很大,可以使用int和long。如果數(shù)值超過18位數(shù)字,就必須使用BigDecimal


第四十九條、基本類型優(yōu)先于裝箱基本類型

  1. java有一個(gè)類型系統(tǒng)由兩個(gè)部分組成:

    基本類型(primitive)如:int、double和boolean;引用類型(reference type)如:String和List。每個(gè)基本類型都有一個(gè)對應(yīng)的引用類型,稱作裝箱基本類型(boxed primitive)。int/double/boolean對應(yīng)于Integer、Double和Boolean。自動(dòng)裝箱和自動(dòng)拆箱模糊了但是沒有完全抹去基本類型和裝箱基本類型之間的區(qū)別。

  2. 兩者之間的主要區(qū)別:

    • 基本類型只有值,而裝箱基本類型則具有與它們的值不同的同一性。
    • 基本類型只有功能完備的值,裝箱基本類型還有個(gè)非功能值null。
    • 基本類型通常比裝箱基本類型更節(jié)省時(shí)間和空間。
  3. 對裝箱基本類型使用==操作符幾乎總是錯(cuò)誤的;當(dāng)一項(xiàng)操作中混合使用基本類型和裝箱基本類型時(shí),裝箱基本類型就會(huì)自動(dòng)拆箱,如果null對象引用被自動(dòng)拆箱,就會(huì)得到一個(gè)NullPointerException

  4. 什么時(shí)候應(yīng)該使用裝箱基本類型呢?

    • 作為集合中的元素、鍵和值,不能將基本類型放在集合中,因此必須使用裝箱基本類型;
    • 在參數(shù)化類型中,必須使用裝箱基本類型作為參數(shù)類型;
    • 在反射的方法調(diào)用時(shí),必須使用裝箱基本類型。
  5. 總結(jié):當(dāng)可以選擇的時(shí)候,基本類型優(yōu)先于裝箱基本類型。基本類型更加簡單也更加快速,如果必須使用裝箱基本類型,則要特別小心,自動(dòng)裝箱減少了使用裝箱基本類型的繁瑣性,但是并沒有減少它的風(fēng)險(xiǎn)。


第五十條、如果使用其他類型更合適,則盡量避免使用字符串

  1. 字符串的優(yōu)點(diǎn):被用來表示文本,十分通用且Java支持的比較好。

  2. 不應(yīng)該使用字符串的情形:

    • 字符串不適合代替其他的值,當(dāng)一段數(shù)據(jù)從文件、網(wǎng)絡(luò)或者鍵盤設(shè)備,進(jìn)入到程序中,通常是以字符串的形式存在,如果它是數(shù)值,就應(yīng)該被轉(zhuǎn)換為適當(dāng)?shù)臄?shù)值類型等等;
    • 字符串不適合替代枚舉類型:見第三十條
    • 字符串不適合代替聚集類型:如果一個(gè)實(shí)體有多個(gè)組件,用字符串表示這個(gè)實(shí)體通常是很不恰當(dāng)?shù)模玫淖龇ó?dāng)然是編寫一個(gè)類來描述這個(gè)數(shù)據(jù)集,通常是一個(gè)私有的靜態(tài)成員類。
    • 字符串不適合代替能力表(capabilities):有時(shí)候,字符串被用于對某種功能進(jìn)行授權(quán)訪問,例如考慮設(shè)計(jì)一個(gè)提供線程局部變量機(jī)制,這個(gè)機(jī)制提供的變量在每個(gè)線程中都有自己的值。幾年前面對這樣的設(shè)計(jì)任務(wù)時(shí),有些人利用客戶提供的字符串鍵,對每個(gè)線程局部變量的內(nèi)容進(jìn)行訪問授權(quán)。
  3. 總之:如果可以使用更加合適的數(shù)據(jù)類型,或者可以編寫更加適當(dāng)?shù)臄?shù)據(jù)類型,就應(yīng)該避免用字符串來表示對象。基本類型、枚舉類型和聚集類型經(jīng)常被錯(cuò)誤地用字符串來代替。

第五十一條、當(dāng)心字符串連接的性能

  1. +(字符串連接操作符)是把多個(gè)字符串合并為一個(gè)字符串的便利途徑。要想產(chǎn)生單獨(dú)一行的輸出,或者構(gòu)造一個(gè)字符串來表示一個(gè)較小的、大小固定的對象,使用+是非常合適的。但是它不適合應(yīng)用在大規(guī)模的場景中,為連接n個(gè)字符串而重復(fù)的使用字符串連接操作符,需要n的平方級的時(shí)間因?yàn)樽址豢勺兌鴮?dǎo)致的,當(dāng)兩個(gè)字符串被連接在一起的時(shí)候,它們的內(nèi)容都要被拷貝。

  2. 為了獲得可以接受的性能,請使用StringBuilder替代String,兩種方法性能差別巨大,原先的做法開銷是隨著數(shù)量呈平方增加,改進(jìn)后是線性增加。

      public String statement(){
          StringBuilder b = new StringBuilder(numItems() *LINE_WIDTH);
          for(int i = 0; i< numItems();i++){
              b.append(lineForItem(i));
          }
          return b.toString();
      }
    

    原先的:

     public String statement(){
       String result = "";
       for (int i = 0;i < numItems(); i++){
           result += lineForItem(i);
       }
       return result;
     }
    
  3. 總結(jié):不要使用字符串連接操作符來合并多個(gè)字符串,除非性能無關(guān)緊要。相反,應(yīng)該使用StringBuilder的append方法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,732評論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,214評論 3 426
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,781評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,588評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,315評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,699評論 1 327
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,698評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,882評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,441評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,189評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,388評論 1 372
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,933評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,613評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,023評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,310評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,112評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,334評論 2 377

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,733評論 18 399
  • 《ilua》速成開發(fā)手冊3.0 官方用戶交流:iApp開發(fā)交流(1) 239547050iApp開發(fā)交流(2) 1...
    葉染柒丶閱讀 10,896評論 0 11
  • 涂洋鎮(zhèn)宮下縣,這一輩有倆孩子,陳貞是出了名的氣運(yùn)低,劉陽則是出了名的混世大魔王。 陳貞是個(gè)早產(chǎn)兒,剛滿月的時(shí)候,陳...
    罕斯閱讀 2,052評論 2 10
  • 申猴年已經(jīng)悄然進(jìn)入尾聲,隨著酉雞年的來臨,各大品牌又到了一年一度利用生肖俘獲人心的時(shí)刻(可是年年失敗,攤手),不過...
    弓十人閱讀 347評論 0 0
  • 常年UI與程序猿,撕來撕去,有的成了老死不相往來的仇人,有的也不乏能成為推心置腹的朋友。(咱們 UI 了解用戶體驗(yàn)...
    圖圖1105閱讀 306評論 2 0