if..else、switch 條件式


為了應付「如果OOO成立」就要…,「否則」就要...的需求,Java提供了if..else條件式,語法如下:

if(條件式) {
    陳述句;
}
else {
    陳述句;
}

條件式運算結果為true會執行if{}中的陳述句,否則執行else{}中的陳述句,如果條件式不成立時並不想作任何事,則else可以省略。

底下來個運用if...else判斷數字為奇數或偶數的範例:

package cc.openhome;

public class Odd {
    public static void main(String[] args) {
        int input = 10;
        int remain = input % 2; 
        if(remain == 1) { // 餘數為1就是奇數
            System.out.printf("%d 為奇數%n", input); 
        }
        else {
            System.out.printf("%d 為偶數%n", input); 
        }
    }
}

如果ifelse中只有一行陳述句,則{}可以省略,不過為了可讀性與可維護性而言,現在建議是就算只有一行陳述句,也要撰寫{與}明確定義範圍。

Apple曾經提交一個 iOS上的安全更新。原因是在某個函式中有兩個連續的縮排:

...      
if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
        goto fail;
        goto fail;
if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
        goto fail;
...

因為縮排在同一層,閱讀程式碼時大概也就沒注意到,又沒有{}定義區塊,結果就是goto fail無論如何都會被執行到的錯誤。

某些人會撰寫所謂的if...else if語法:

if(條件式一) {
    ...
}
else if(條件式二) {
    ...
}
else {
    ...
}

其實Java中並沒有真的有if...else if的語法,這是省略{}加上程式碼排版後的結果,如果不省略{},原本的程式應該是:

if(條件式一) {
    ...
}
else {
    if(條件式二) {
        ...
    }
    else {
        ...
    }
}

如果條件式一不滿足,就執行else中的陳述,而在這邊進行條件式二測試,如果滿足就執行條件式二{}中的陳述,如果省略了第一個else{}

if(條件式一) {
    ...
}
else
    if(條件式二) {
        ...
    }
    else {
        ...
    }

由於Java是個自由格式語言,可以適當地排列這個片段,就會變為方才看到的if...else if寫法,就閱讀上似乎比較好讀一些,例如應用在處理學生的成績等級問題:

package cc.openhome;

public class Level {
    public static void main(String[] args) {
        int score = 88;
        char level; 
        if(score >= 90) {
            level = 'A';
        } 
        else if(score >= 80 && score < 90) {
            level = 'B';
        }
        else if(score >= 70 && score < 80) {
            level = 'C';
        }
        else if(score >= 60 && score < 70) {
            level = 'D';
        }        
        else {
            level = 'E';
        }
        System.out.printf("得分等級:%c%n", level);
    }
}

不過就這個例子而言,效率並不好,在最差的情況下,也就是成績小於60分的情況下,總共要從score變數中取出7次的值。就這個例子而言,改用稍後要說明的switch會比較好...

如果isOpenedboolean型態,想在if中作判斷,請別這麼寫:

if(isOpened == true) {
    ...
}

這樣程式是也可以正確執行,只不過很遜,你只要如下撰寫就好了,可讀性也會比較好:

if(isOpened) {
    ...
}

在JDK7之前,switch可用於比對整數、字元、Enum,在JDK7之後,增加了對字串的比對,Enum時之後會再詳細說明。switch的語法架構如下:

switch(變數或運算式) {
    case 整數、字元、字串或Enum:
        陳述句;
        break;
    case 整數、字元、字串或Enum:
        陳述句;
        break;
    ...
    default:
        陳述句;
}


首先看看switch的括號,當中置放要取得值的變數或運算式,值必須是整數、字元、字串或Enum,取得值後會開始與case中設定的整數、字元、字串或Enum比對,如果符合就執行之後的陳述句,直到遇到break離開switch區塊,如果沒有符合的整數、字元、字串或Enum,則會執行default後的陳述句,default不一定需要,如果沒有預設要處理的動作,可以省略default

來看看 Level類別,如何改用switch實作:

package cc.openhome;

public class Level2 {
    public static void main(String[] args) {
        int score = 88;
        int quotient = score / 10;
        char level;
        switch(quotient) { 
            case 10: 
            case 9: 
                level = 'A';
                break; 
            case 8: 
                level = 'B';
                break; 
            case 7: 
                level = 'C';
                break; 
            case 6: 
                level = 'D';
                break; 
            default: 
                level = 'E';
        }
        System.out.printf("得分等級:%c%n", level);
    }
}

在這個程式中,使用除法並取得運算後的商數,如果大於90的話,除以10的商數一定是9或10(100分時),在case 10中沒有任何的陳述,也沒有使用break,所以繼續往下執行,直到遇到break離開switch為止,所以學生成績100分的話,也會顯示A的成績等級;如果比對條件不在10到6這些值的話,會執行default下的陳述,這表示商數小於6,所以學生成績等級就顯示為E了。

這個程式與前一個範例使用if..else來判斷成績等級有何不同?這個程式只會在一開始的switch括號中取出quotient變數的值一次,然後將這個值與之後case比對,所以效率上比較好。