為什麼你的程式會亂跑?搞懂Java的控制流程(Controlling Execution)【Thinking in Java筆記(3-1)】

為什麼你的程式會亂跑?搞懂Java的控制流程(Controlling Execution)【Thinking in Java筆記(3-1)】
Photo by orbtal media / Unsplash

在學習 Java 程式設計時,瞭解如何控制程式的執行流程是非常重要的。這篇文章將介紹 Java 中的條件語句和迴圈結構,幫助初學者掌握程式的控制邏輯。

true 和 false:布林世界的二元哲學

所有的條件判斷在 Java 裡都依賴布林值 truefalse。這裡沒有灰色地帶,也沒有「大概是對」這種藉口

嚴格的布林值規則

Java 很認真。它不像 C 語言那樣,會讓你用 0 當成 false,然後任何非 0 都默默當作 true

在 Java 中,你不能寫 if(a) 來測試一個數字,而是要明確寫成 if(a != 0)。語法潔癖?是的,這就是 Java

if-else 語句:基本結構

以下是 Java 裡最基本的 if-else 使用方式:

if (BooleanExpression)
  statement
// 或
if (BooleanExpression)
    statement
else
    statement
小提醒:「statement」就是一行有效的 Java 指令,例如 System.out.println("Hello") 這種

實際應用:判斷數字大小

public class IfElse {
  static int result = 0;
  static void test(int testval, int target) {
    if(testval > target)
      result = +1;
    else if(testval < target)
      result = -1;
    else
      result = 0; // Match
  }
  public static void main(String[] args) {
    test(10, 5);
    System.out.println(result); // 輸出 1
    test(5, 10);
    System.out.println(result); // 輸出 -1
    test(5, 5);
    System.out.println(result); // 輸出 0
  }
} /* Output:
1
-1
0
*/

在這段程式中,test() 方法會比較兩個數字大小,然後根據結果更新靜態變數 result 的值。main() 方法則呼叫這個方法來驗證各種情況,並列印出結果

這段程式碼的重點,不是展示什麼炫技操作,而是幫助你練好邏輯思考的基本功——這是每位寫程式的人都得經歷的第一道關卡

不再手動重複勞動:搞懂 Java 中的迴圈(Iteration)

寫程式的某種本質,就是「重複做事但不想重複敲鍵盤」。而 Java 的迴圈,就是為了讓你能優雅地重複某段邏輯,不必像古代人那樣 Ctrl+C / Ctrl+V

while 迴圈:條件控制的守門員

while 迴圈就像一個問問題的警衛:每次你想執行點什麼,它都會問你一次「條件還成立嗎?」如果你說「是」,它就讓你進去(執行一次迴圈內容),否則就把你請走(跳出迴圈)

語法

while(Boolean-expression)
  statement

範例

來看看一個簡單的 while 迴圈範例,幫助你理解它怎麼運作:

public class WhileTest {
  static boolean condition() {
    boolean result = Math.random() < 0.99;
    System.out.print(result + ", ");
    return result;
  }
  public static void main(String[] args) {
    while(condition())
      System.out.println("Inside 'while'");
    System.out.println("Exited 'while'");
  }
}

這段程式碼的作用是:每次執行 condition() 都會有 99% 的機率返回 true,因此 while 迴圈大多數時候會重複執行「Inside 'while'」這行,直到有一次運氣不好,產生的數大於等於 0.99,才會跳出來

  • condition() 方法會每次產生一個小於 1 的隨機數
  • 如果這個數字小於 0.99,就回傳 true,迴圈繼續執行並印出「Inside 'while'」
  • 如果回傳 false(機率約 1%),就跳出迴圈,印出「Exited 'while'」

do-while 迴圈:你先幹了再說

do-while 是 Java 中唯一「保證至少執行一次」的迴圈。它不像其他迴圈那樣先檢查條件,而是先執行內容,再來問條件成不成立

最典型的例子就是「使用者輸入」。你總得先讓使用者輸入東西,然後才知道要不要再讓他輸入一次吧?像這樣的互動流程,就非常適合用 do-while 來寫

舉例來說:

  • 建立登入畫面時,至少要顯示一次輸入介面,然後根據帳密正確與否判斷是否要重試
  • 做選單系統時,先顯示一次選單,再依照使用者的選項進行後續動作

所以簡單來說:當你需要「一定要跑一次」的邏輯,do-while 就是你的好朋友

語法

do
  statement
while (BooleanExpression);

範例

public class DoWhileExample {
	public static void main(String[] args) {
		int count = 0;
		do {
			System.out.println("Count is: " + count);
			count++;
		} while (count < 5);
	}
}

這段範例其實就像是在數人頭,只是用程式做的:

  • 一開始 count 是 0,所以程式先執行一次 do 區塊,印出「Count is: 0」
  • 然後它會問:count 小於 5 嗎?如果是,就再做一次
  • 每次跑完一次,count 就會加一,直到不小於 5 為止

實際用途呢?假設你有一個遊戲選單,第一次一定要先顯示給玩家看(不然他要按什麼?),然後只要玩家還沒選「退出」,你就繼續重複這個選單。這種「至少執行一次」的邏輯,就是 do-while 存在的意義

for 迴圈:井然有序的三段式重複器

在所有的迴圈中,for 是最常出現的老朋友。它的結構清晰明瞭,非常適合處理「我知道要做幾次」的情況。你可以把它想成一個待辦清單管理器:設定起點、決定何時停、每次該怎麼更新進度,通通一次搞定

這也正是它跟 while 的最大差異:while 比較像是你在等一個不確定的事件(像是等快遞送達),而 for 比較像是你要刷牙 3 次,就寫 for (次數) 然後開始刷,幾次就幾次,剛剛好

語法

for (初始化; 條件判斷; 更新步驟)
  statement
  • 初始化:設定計數器的初始值,通常像是 int i = 0
  • 條件判斷:每次進入迴圈前檢查是否繼續,像是 i < 10
  • 更新步驟:每次迴圈執行完後更新變數,像是 i++

三個部分都可以留空,這提供了需要時的靈活性。

範例

public class ListCharacters {
  public static void main(String[] args) {
    for(char c = 0; c < 128; c++)
      if(Character.isLowerCase(c))
        System.out.println("value: " + (int)c + " character: " + c);
  }
} /* Output:
value: 97 character: a
value: 98 character: b
value: 99 character: c
value: 100 character: d
value: 101 character: e
value: 102 character: f
value: 103 character: g
value: 104 character: h
value: 105 character: i
value: 106 character: j
...
*/

這段程式碼示範了如何用 for 迴圈從 ASCII 表中找出所有的小寫字母,並印出每個字母對應的數值與字元

但講白一點,這不是你每天都會寫的程式。這個範例的重點在於讓你熟悉 for 迴圈的寫法:從一個明確的起點開始(這裡是 char c = 0),每次檢查是否還在條件內(c < 128),並做出固定的更新(c++

真實世界中,for 迴圈常用來:

  • 處理一段固定長度的資料(像是讀入的檔案每一行)
  • 重複進行某些特定次數的操作(例如建立 UI 元素、模擬運算、跑 benchmark)
  • 在你還沒學會用 foreach 的時候,對陣列內容進行操作

總之,for 迴圈的強項在於「控制感」強,適合你已經知道「要跑幾次」、「從哪開始」和「每次要怎麼走一步」的場合

逗號運算子:多工的小幫手

在 Java 裡,逗號運算子沒什麼存在感,它不像加減乘除那樣常見。但在 for 迴圈的括號內,它有一點小用武之地

你可以在初始化或更新步驟裡,同時處理多個變數。這讓你可以同時追蹤兩件事情,比如一個計數器和一個對應的值,讓你的程式更緊湊,不必寫兩個分開的變數區塊

使用情境?

  • 同時追蹤多個變數的關聯變化(像是 i 遞增、j 根據 i 變化)
  • 不想把程式拆得七零八落,想要一行裡控制兩件小事
  • 在 LeetCode 這種題目裡同時處理兩個索引(雙指標)

不過實務上,除非你有一個明確需要,不然還是建議寫清楚比較容易維護,不要為了帥氣而讓自己三週後看不懂自己在幹嘛

範例

public class CommaOperator {
  public static void main(String[] args) {
    for(int i = 1, j = i + 10; i < 5; i++, j = i * 2) {
      System.out.println("i = " + i + " j = " + j);
    }
  }
} /* Output:
i = 1 j = 11
i = 2 j = 4
i = 3 j = 6
i = 4 j = 8
*/

在這個例子中,我們設定兩個變數 ij

  • i 是主要的計數器,從 1 開始,直到小於 5。
  • j 則根據 i 的值進行更新:一開始是 i + 10,之後每次迴圈執行時變為 i * 2

這種寫法的好處是可以在同一個 for 迴圈中同時追蹤並操作兩個有關聯的變數,非常適合用在雙指標法、矩陣對角線掃描或是同時處理兩組資料的時候

這樣做不僅能讓程式碼更濃縮,邏輯也變得更集中。但要注意,可讀性也是工程的一部分,不要寫到連三天後的你自己都看不懂

foreach 迴圈:Java 的懶人迴圈,實際上是日常最常用的武器

如果你只想把一個陣列或清單裡的元素一個個拿出來處理,而不想煩索引那些東西,那 foreach(也稱 enhanced for loop)會是你的首選

這個語法是在 Java SE5(也就是 Java 1.5)才加入的,是 Java 為了讓開發者能更簡潔地處理集合而新增的語法糖。雖然它還是使用 for 當關鍵字,但這其實是另一種專門用來遍歷陣列和集合的語法,讓你不需要手動寫索引邏輯,直接就能處理每個元素

如果你是從 PHP 來的讀者,這概念就很熟悉。PHP 早就有 foreach ($list as $item) 這種結構了,而 Java 是後來才補上這個開發者友善功能。其他語言會用不同的關鍵字(像 Python 用 for item in list),但 Java 就是繼續沿用 for,只是語法變得更輕巧

語法

for (元素類型 變數 : 陣列或集合) {
    語句;
}

為什麼你會天天用到它?

幾乎所有日常開發任務都需要「對每個東西做一件事」:

  • 處理一個使用者清單中的每個帳號
  • 檢查資料庫查詢結果是否符合條件
  • 對每個設定檔欄位執行驗證
  • 送出每筆訂單通知

以前你可能得寫這種傳統寫法:

for (int i = 0; i < list.length; i++) {
    System.out.println(list[i]);
}

foreach 可以變成這樣:

for (String item : list) {
    System.out.println(item);
}

簡潔、清楚、少出錯

什麼時候不要用?

當你需要知道元素的索引、或是你要在遍歷時修改集合內容(像是新增或移除元素)時,foreach 可能就不太適合。這時候你還是得乖乖用傳統 for

範例

public class ForEachFloat {
  public static void main(String[] args) {
    Random rand = new Random(47);
    float f[] = new float[10];
    for(int i = 0; i < 10; i++)
      f[i] = rand.nextFloat();
    for(float x : f)
      System.out.println(x);
  }
} /* Output:
0.72711575
0.39982635
0.5309454
0.0534122
0.16020656
0.57799757
0.18847865
0.4170137
0.51660204
0.73734957
*/

在這個範例中,我們透過 foreach 迴圈來處理一個看似日常但非常實用的任務──列出一組隨機浮點數。

  • 首先,我們使用 Java 的 Random 類別產生 10 個浮點數,模擬像是從感應器收集的資料、模擬數據、或某種測試用輸入
  • 接著使用 foreach(也就是 enhanced for loop)來遍歷這些數值,逐一列印出來

這種寫法不但簡潔,還能讓你專注在「對每個元素做什麼」這件事,而不是去煩惱索引該怎麼寫,尤其在處理陣列或集合時特別常見。

例如:你讀入了一個 CSV 檔案中的每一列金額,想快速印出來檢查;或是你在測試某個函式的回傳值陣列。這時候,foreach 就是你最直接、最少出錯的選擇

結論

控制流程是每一門程式語言的核心骨架,而 Java 對這部分的設計不只是嚴謹,更是為了讓開發者能寫出清晰、有邏輯的程式

從條件判斷到各種迴圈結構,我們學到的不只是語法本身,而是如何把重複、選擇、邏輯決策這些「程式的大腦」寫進一段段可讀又可控的程式碼中

初學者在學習這些東西時,常常會有「這些結構好像都很簡單,但又不知道實際能做什麼」的困惑。希望這篇文章除了教你語法,也讓你看見這些語法怎麼應用在真實世界:從處理使用者輸入,到遍歷資料清單,甚至建立互動式介面

如果你能掌握這些基本功,未來無論是寫遊戲邏輯、後端 API、還是做資料處理,控制流程都會是你每天都要用到的工具箱──學會怎麼用、用得漂亮,比你背多少語法都重要