Java開(kāi)發(fā) 控制語(yǔ)句

2021-03-23 10:19 更新

\1. 【強(qiáng)制】在一個(gè) switch 塊內(nèi),每個(gè) case 要么通過(guò) continue/break/return 等來(lái)終止,要么注釋說(shuō)明程序?qū)⒗^續(xù)執(zhí)行到哪一個(gè) case 為止;在一個(gè) switch 塊內(nèi),都必須包含一個(gè) default語(yǔ)句并且放在最后,即使它什么代碼也沒(méi)有。

  • 說(shuō)明:注意 break 是退出 switch 語(yǔ)句塊,而 return 是退出方法體。

\2. 【強(qiáng)制】當(dāng) switch 括號(hào)內(nèi)的變量類(lèi)型為 String 并且此變量為外部參數(shù)時(shí),必須先進(jìn)行 null判斷。

  • 反例:如下的代碼輸出是什么?

public class SwitchString {
    public static void main(String[] args) {
        method(null);
    }
    public static void method(String param) {
        switch (param) {
            // 肯定不是進(jìn)入這里
            case "sth":
            System.out.println("it's sth");
            break;
            // 也不是進(jìn)入這里
            case "null":
            System.out.println("it's null");
            break;
            // 也不是進(jìn)入這里
            default:
            System.out.println("default");
        }
    } 
}

\3. 【強(qiáng)制】在 if/else/for/while/do 語(yǔ)句中必須使用大括號(hào)。

  • 說(shuō)明:即使只有一行代碼,也禁止不采用大括號(hào)的編碼方式:if (condition) statements;

\4. 【強(qiáng)制】三目運(yùn)算符 condition? 表達(dá)式 1 : 表達(dá)式 2 中,高度注意表達(dá)式 1 和 2 在類(lèi)型對(duì)齊時(shí),可能拋出因自動(dòng)拆箱導(dǎo)致的 NPE 異常。

  • 說(shuō)明:以下兩種場(chǎng)景會(huì)觸發(fā)類(lèi)型對(duì)齊的拆箱操作: 1) 表達(dá)式 1 或表達(dá)式 2 的值只要有一個(gè)是原始類(lèi)型。 2) 表達(dá)式 1 或表達(dá)式 2 的值的類(lèi)型不一致,會(huì)強(qiáng)制拆箱升級(jí)成表示范圍更大的那個(gè)類(lèi)型。

  • 反例:

Integer a = 1;
Integer b = 2;
Integer c = null;
Boolean flag = false;
// a*b 的結(jié)果是 int 類(lèi)型,那么 c 會(huì)強(qiáng)制拆箱成 int 類(lèi)型,拋出 NPE 異常
Integer result=(flag? a*b : c);

\5. 【強(qiáng)制】在高并發(fā)場(chǎng)景中,避免使用”等于”判斷作為中斷或退出的條件。

  • 說(shuō)明:如果并發(fā)控制沒(méi)有處理好,容易產(chǎn)生等值判斷被“擊穿”的情況,使用大于或小于的區(qū)間判斷條件來(lái)代替。

  • 反例:判斷剩余獎(jiǎng)品數(shù)量等于 0 時(shí),終止發(fā)放獎(jiǎng)品,但因?yàn)椴l(fā)處理錯(cuò)誤導(dǎo)致獎(jiǎng)品數(shù)量瞬間變成了負(fù)數(shù),這樣的話(huà),活動(dòng)無(wú)法終止。

\6. 【推薦】當(dāng)某個(gè)方法的代碼總行數(shù)超過(guò) 10 行時(shí),return / throw 等中斷邏輯的右大括號(hào)后均需要加一個(gè)空行。

  • 說(shuō)明:這樣做邏輯清晰,有利于代碼閱讀時(shí)重點(diǎn)關(guān)注。

\7. 【推薦】表達(dá)異常的分支時(shí),少用 if-else 方式,這種方式可以改寫(xiě)成:

if (condition) { 
    ...
    return obj; 
}
// 接著寫(xiě) else 的業(yè)務(wù)邏輯代碼; 

  • 說(shuō)明:如果非使用 if()...else if()...else...方式表達(dá)邏輯,避免后續(xù)代碼維護(hù)困難,請(qǐng)勿超過(guò) 3 層。

  • 正例:超過(guò) 3 層的 if-else 的邏輯判斷代碼可以使用衛(wèi)語(yǔ)句、策略模式、狀態(tài)模式等來(lái)實(shí)現(xiàn),其中衛(wèi)語(yǔ)句

示例如下:

public void findBoyfriend (Man man) {
    if (man.isUgly()) {
        System.out.println("本姑娘是外貌協(xié)會(huì)的資深會(huì)員");
        return;
    }
    if (man.isPoor()) {
        System.out.println("貧賤夫妻百事哀");
        return;
    }
    if (man.isBadTemper()) {
        System.out.println("銀河有多遠(yuǎn),你就給我滾多遠(yuǎn)");
        return; 
    }
    System.out.println("可以先交往一段時(shí)間看看");
}

\8. 【推薦】除常用方法(如 getXxx/isXxx)等外,不要在條件判斷中執(zhí)行其它復(fù)雜的語(yǔ)句,將復(fù)雜邏輯判斷的結(jié)果賦值給一個(gè)有意義的布爾變量名,以提高可讀性。

  • 說(shuō)明:很多 if 語(yǔ)句內(nèi)的邏輯表達(dá)式相當(dāng)復(fù)雜,與、或、取反混合運(yùn)算,甚至各種方法縱深調(diào)用,理解成本非常高。如果賦值一個(gè)非常好理解的布爾變量名字,則是件令人爽心悅目的事情。

  • 正例:

// 偽代碼如下
final boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
if (existed) {
    ...
}

  • 反例:

public final void acquire ( long arg) {
    if (!tryAcquire(arg) &&
    acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
        selfInterrupt();
    }
}

\9. 【推薦】不要在其它表達(dá)式(尤其是條件表達(dá)式)中,插入賦值語(yǔ)句。

說(shuō)明:賦值點(diǎn)類(lèi)似于人體的穴位,對(duì)于代碼的理解至關(guān)重要,所以賦值語(yǔ)句需要清晰地單獨(dú)成為一行。

  • 反例:

public Lock getLock(boolean fair) {
    // 算術(shù)表達(dá)式中出現(xiàn)賦值操作,容易忽略 count 值已經(jīng)被改變
    threshold = (count = Integer.MAX_VALUE) - 1;
    // 條件表達(dá)式中出現(xiàn)賦值操作,容易誤認(rèn)為是 sync==fair
    return (sync = fair) ? new FairSync() : new NonfairSync();
}

10.【推薦】循環(huán)體中的語(yǔ)句要考量性能,以下操作盡量移至循環(huán)體外處理,如定義對(duì)象、變量、獲取數(shù)據(jù)庫(kù)連接,進(jìn)行不必要的 try-catch 操作(這個(gè)try-catch 是否可以移至循環(huán)體外)。

11.【推薦】避免采用取反邏輯運(yùn)算符。

  • 說(shuō)明:取反邏輯不利于快速理解,并且取反邏輯寫(xiě)法一般都存在對(duì)應(yīng)的正向邏輯寫(xiě)法。
  • 正例:使用 if (x < 628) 來(lái)表達(dá) x 小于 628。
  • 反例:使用 if (!(x >= 628)) 來(lái)表達(dá) x 小于 628。

12.【推薦】公開(kāi)接口需要進(jìn)行入?yún)⒈Wo(hù),尤其是批量操作的接口。

  • 反例:某業(yè)務(wù)系統(tǒng),提供一個(gè)用戶(hù)批量查詢(xún)的接口,API 文檔上有說(shuō)最多查多少個(gè),但接口實(shí)現(xiàn)上沒(méi)做任何保護(hù),導(dǎo)致調(diào)用方傳了一個(gè) 1000 的用戶(hù) id 數(shù)組過(guò)來(lái)后,查詢(xún)信息后,內(nèi)存爆了。

13.【參考】下列情形,需要進(jìn)行參數(shù)校驗(yàn):

1) 調(diào)用頻次低的方法。

2) 執(zhí)行時(shí)間開(kāi)銷(xiāo)很大的方法。此情形中,參數(shù)校驗(yàn)時(shí)間幾乎可以忽略不計(jì),但如果因?yàn)閰?shù)錯(cuò)誤導(dǎo)致 中間執(zhí)行回退,或者錯(cuò)誤,那得不償失。

3) 需要極高穩(wěn)定性和可用性的方法。

4) 對(duì)外提供的開(kāi)放接口,不管是 RPC/API/HTTP 接口。

5) 敏感權(quán)限入口。

14.【參考】下列情形,不需要進(jìn)行參數(shù)校驗(yàn):

1) 極有可能被循環(huán)調(diào)用的方法。但在方法說(shuō)明里必須注明外部參數(shù)檢查。

2) 底層調(diào)用頻度比較高的方法。畢竟是像純凈水過(guò)濾的最后一道,參數(shù)錯(cuò)誤不太可能到底層才會(huì)暴露問(wèn)題。一般 DAO 層與 Service 層都在同一個(gè)應(yīng)用中,部署在同一臺(tái)服務(wù)器中,所以 DAO 的參數(shù)校驗(yàn),可以省略。

3) 被聲明成 private 只會(huì)被自己代碼所調(diào)用的方法,如果能夠確定調(diào)用方法的代碼傳入?yún)?shù)已經(jīng)做過(guò)檢查或者肯定不會(huì)有問(wèn)題,此時(shí)可以不校驗(yàn)參數(shù)。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)