Logo

新人日誌

首頁關於我部落格

新人日誌

Logo

網站會不定期發佈技術筆記、職場心得相關的內容,歡迎關注本站!

網站
首頁關於我部落格
部落格
分類系列文

© 新人日誌. All rights reserved. 2020-present.

Java 新手入門:理解主類別與程式基本結構

最後更新:2025年2月15日程式語言

本文為 Java 基礎入門 系列文,第 6 篇:

  1. Java 程式語言入門指南:從基礎到實踐
  2. Java、Python、JavaScript 的執行方式解析:直譯器、虛擬機與 JavaScript 引擎的區別
  3. OpenJDK 完全指南:適合初學者的入門介紹
  4. 使用 Scoop 安裝 OpenJDK 的完整指南
  5. Oracle 是公司還是軟體?完整解析與詳細介紹
  6. Java 新手入門:理解主類別與程式基本結構 👈進度
  7. Java 類別的存取權限(Access Modifiers)
  8. Java 方法的返回值與關鍵字詳解
  9. Java 方法的參數詳解:類型、規格與標準方法簽名
  10. Java 是強型態語言嗎?完整解析與新手指南

Java 作為全球熱門的程式語言,被廣泛應用於網站開發、Android 應用程式、企業級系統等領域。

對於初學者來說,掌握 Java 的基本結構是踏入開發世界的第一步。

本文將深入解析 主類別(Main Class) 的核心概念、程式執行邏輯,以及常見的檔案命名規則,並透過範例程式碼幫助新手建立扎實的基礎。

建議閱讀本文前,先具備相關概念:

  • 物件導向是什麼?|JavaScript 四大物件特性簡介|初學者筆記(1)
  • 初學者指南:深入了解 Python 類別方法

Java 程式的基本結構

類別(Class)與方法(Method)

Java 程式由 類別 組成,每個類別中可包含多個 方法(類似於其他語言中的函式)。

而程式的執行必定從 main 方法開始,這是 Java 虛擬機(JVM)的強制要求。

最小可執行程式範例

以下是一個經典的 Hello, Java! 程式:

public class HelloJava {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}
  • 執行流程:
    JVM 會從 main 方法開始執行,並輸出 Hello, Java!。

為什麼 Java 程式一定要從 main 方法開始?

想像你在玩一款電腦遊戲,每個遊戲都會有個「開始遊戲」的按鈕,按下去後遊戲才會正式運行。

在 Java 裡,這個「開始遊戲」的角色就是 main 方法。

當你執行 Java 程式時,Java 虛擬機(JVM)就像是遊戲的主控系統,它會按照以下步驟來執行程式:

  1. 啟動 Java 虛擬機(JVM)。
  2. 找到你寫的 Java 類別(Class)。
  3. 在類別裡尋找 main 方法(因為這是 Java 規定的進入點)。
  4. 執行 main 方法裡的程式碼,開始運作。

如果你的程式裡沒有 main 方法,JVM 會不知道該從哪裡開始,結果就會報錯,導致程式無法執行。

下面是 JVM 執行 Java 程式的過程:

graph TD;
    A[啟動 Java 程式] --> B[JVM 啟動]
    B --> C{找到 main 方法?}
    C -- 是 --> D[執行 main 方法]
    D --> E[程式開始運作]
    C -- 否 --> F[報錯:找不到 main 方法!]
    F --> G[程式終止]

為什麼 main 方法一定要是 static?

在 Java 中,所有的程式碼都必須寫在類別(Class)裡。

但有一個問題——當 JVM 啟動時,還沒有任何物件存在,那麼 JVM 要怎麼執行程式呢?

Java 方法的執行方式

在 Java 裡,一般的方法(非 static 方法)都必須透過物件來呼叫,例如:

class MyClass {
    void sayHello() {  // 這是一個非 static 方法
        System.out.println("Hello!");
    }

    public static void main(String[] args) {
        MyClass obj = new MyClass(); // 先建立物件
        obj.sayHello(); // 再透過物件呼叫方法
    }
}

在這個例子中,sayHello() 不是 static,所以我們必須先用 new MyClass() 建立 MyClass 的物件,然後才能呼叫 sayHello() 方法。

但問題是,當 Java 程式剛開始執行時,JVM 還沒辦法知道該怎麼建立物件!

JVM 啟動時還沒有物件

當 JVM 啟動 Java 應用程式時,它只知道要執行某個類別,但它不會自動建立物件,因為它不知道該怎麼做。

如果 main 不是 static,那 JVM 就會遇到這個問題:

  1. JVM 需要呼叫 main 方法開始執行程式。
  2. 但如果 main 不是 static,JVM 需要先建立這個類別的物件。
  3. 然而,JVM 並不知道該怎麼建立物件,因為可能需要傳入參數,或是類別的建構子(Constructor)可能有特別的邏輯。
  4. 結果 JVM 進入「無限迴圈」的困境,程式無法啟動。

所以,為了讓 JVM 能夠順利啟動程式,main 必須是 static,這樣 JVM 才能直接執行它,而不需要先建立物件。

static 讓 main 可以直接執行

當一個方法被標記為 static,代表它是類別層級的方法,不屬於任何物件。

也就是說,我們可以直接透過類別名稱呼叫它,而不需要建立物件。

舉個例子:

class MyClass {
    static void sayHello() {  // 這是一個 static 方法
        System.out.println("Hello!");
    }

    public static void main(String[] args) {
        MyClass.sayHello(); // 直接用類別名稱呼叫,不需要建立物件
    }
}

在這裡,sayHello() 是 static,所以我們不需要 new MyClass(),可以直接用 MyClass.sayHello() 來執行它。

同樣地,main 方法被設為 static,JVM 就可以直接執行它,而不需要先建立物件。

如果 main 不是 static 會發生什麼事?

如果我們嘗試這樣寫:

class MyClass {
    void main(String[] args) {  // 不是 static
        System.out.println("Hello, Java!");
    }
}

當我們執行這個程式時,JVM 會報錯:

Error: Main method is not static in class MyClass, please define the main method as:
   public static void main(String[] args)

這是因為 JVM 需要 static 方法來當作程式的進入點,如果 main 不是 static,它就無法正確執行程式。

多個 static 方法不會衝突

static 方法只是屬於類別本身的方法,你可以在類別內定義多個 static 方法,它們彼此獨立,互不影響。例如:

class MyClass {
    static void sayHello() {  
        System.out.println("Hello!");
    }

    static void sayGoodbye() {  
        System.out.println("Goodbye!");
    }

    public static void main(String[] args) {
        MyClass.sayHello();  // 呼叫 sayHello()
        MyClass.sayGoodbye(); // 呼叫 sayGoodbye()
    }
}

執行結果

Hello!
Goodbye!

這裡 sayHello() 和 sayGoodbye() 都是 static,我們可以直接用 MyClass.sayHello() 和 MyClass.sayGoodbye() 來呼叫它們,不需要建立物件。

JVM 只會執行 main 方法

即使你定義了多個 static 方法,JVM 在執行 Java 程式時,只會尋找 public static void main(String[] args) 這個方法作為進入點。

其他 static 方法不會自動執行,除非 main 方法主動呼叫它們。

示範:有多個 static 方法,但 JVM 只執行 main

class MyClass {
    static void methodA() {
        System.out.println("這是 methodA");
    }

    static void methodB() {
        System.out.println("這是 methodB");
    }

    public static void main(String[] args) {
        System.out.println("程式開始執行");
    }
}

執行結果

程式開始執行

這裡 methodA() 和 methodB() 不會自動執行,因為 JVM 只會執行 main 方法,而 main 方法裡並沒有呼叫這兩個方法。

main 方法可以主動呼叫其他 static 方法

如果你希望其他 static 方法執行,你需要在 main 方法內明確地呼叫它們。例如:

class MyClass {
    static void methodA() {
        System.out.println("這是 methodA");
    }

    static void methodB() {
        System.out.println("這是 methodB");
    }

    public static void main(String[] args) {
        System.out.println("程式開始執行");
        methodA(); // 呼叫 methodA
        methodB(); // 呼叫 methodB
    }
}

執行結果

程式開始執行
這是 methodA
這是 methodB

這次 methodA() 和 methodB() 都有被 main 方法呼叫,所以它們會被執行。


為什麼 JVM 不能自動建立物件來執行 main?

有人可能會問:「JVM 為什麼不乾脆自己 new 一個物件來呼叫 main 呢?」

有幾個原因:

類別的建構子可能需要參數

class MyClass {
    MyClass(int x) {}  // 需要參數
    
    void main(String[] args) { 
        System.out.println("Hello!"); 
    }
}

在這種情況下,JVM 不知道應該傳入什麼數值來建立 MyClass 的物件,所以無法自動執行 main。

類別可能有特殊的初始化邏輯

class MyClass {
    private MyClass() {} // 私有建構子,禁止建立物件
    
    void main(String[] args) { 
        System.out.println("Hello!"); 
    }
}

如果建構子是 private,JVM 根本無法建立物件,因此 main 不能是一般的方法。

物件建立可能會影響效能


Java 的設計目標之一是高效能和靈活性,如果 JVM 在每次啟動程式時都要自動建立物件,那麼對於一些大型專案來說,這可能會造成額外的開銷,降低執行效率。


public class 的關鍵作用

public class 的定義

public class HelloJava 的結構包含三個部分:

  • public:表示類別是公開的,允許其他類別存取。
  • class:宣告一個類別。
  • HelloJava:類別名稱,需遵守命名慣例(首字母大寫)。

檔案名稱的強制規則

Java 要求 public class 的名稱必須與 .java 檔案名稱完全一致。

  • ✅ 正確範例:類別名 HelloJava → 檔案名 HelloJava.java
  • ❌ 錯誤範例:類別名 HelloJava → 檔案名 Test.java

錯誤示範與解決方案

若將以下程式存為 Test.java:

public class HelloJava { // 類別名稱與檔案名稱不符
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}

編譯時會出現錯誤:

Test.java:1: error: class HelloJava is public, should be declared in a file named HelloJava.java

.class 與 .java 的關係

一個 .java 檔案能產生多個 .class 檔案

當你在一個 .java 檔案內定義多個類別時,Java 會為每個類別產生對應的 .class 檔案,無論這些類別是否是 public。

範例:一個 .java 產生多個 .class

檔案名稱:Test.java

// 這個類別沒有 public,所以檔案名稱不必是 HelloWorld
class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

// 另一個類別
class AnotherClass {
    void sayHello() {
        System.out.println("這是 AnotherClass");
    }
}

編譯這個 .java 檔案

當我們執行:

javac Test.java

Java 會產生兩個 .class 檔案:

HelloWorld.class
AnotherClass.class

這是因為:

  • javac 會自動為 .java 檔案內的每個類別生成對應的 .class 檔案。
  • 每個 .class 檔案的名稱,會與該類別的名稱相同。

執行哪個 .class 檔案?

雖然 Test.java 產生了兩個 .class 檔案,但我們執行 Java 程式時,必須指定 main 方法所在的類別,也就是:

java HelloWorld

執行結果

Hello, World!

但如果我們嘗試執行:

java AnotherClass

會報錯:

Error: Could not find or load main class AnotherClass<br>

這是因為 AnotherClass 裡沒有 main 方法,所以 JVM 不知道從哪裡開始執行程式。

如果有 public 類別,檔案名稱必須與 public class 相同

Java 允許多個類別定義在同一個 .java 檔案內,但只能有一個 public 類別,且檔案名稱必須與這個 public class 名稱一致。

範例

檔案名稱:MainClass.java

// 這是 public 類別,所以檔案名稱必須是 MainClass.java
public class MainClass {
    public static void main(String[] args) {
        System.out.println("這是 MainClass");
    }
}

// 這些不是 public,所以它們的名稱不受檔案名稱限制
class AnotherClass {
    void sayHello() {
        System.out.println("這是 AnotherClass");
    }
}

class ThirdClass {
    void saySomething() {
        System.out.println("這是 ThirdClass");
    }
}

編譯 MainClass.java

javac MainClass.java

這會產生:

MainClass.class
AnotherClass.class
ThirdClass.class
  • MainClass.class → 對應 public class MainClass
  • AnotherClass.class → 對應 class AnotherClass
  • ThirdClass.class → 對應 class ThirdClass

執行

java MainClass

輸出:

這是 MainClass

如果嘗試:

java AnotherClass

則會報錯,因為 AnotherClass 沒有 main 方法。


為什麼 public class 的名稱必須與 .java 檔案名稱完全一致?

在 Java 中,如果一個類別(class)被宣告為 public,那麼它的檔案名稱(.java 檔案)必須與這個 public class 的名稱相同,這是 Java 編譯器強制要求的規則。

確保 Java 檔案和類別名稱一致,方便管理與存取

Java 設計之初,就考慮到大型專案的可讀性與管理性。

要求 public class 名稱與 .java 檔名一致,可以讓開發者透過檔案名稱,就能快速找到對應的類別。

舉個例子,如果你有一個 public class HelloWorld,它的檔案名稱必須是 HelloWorld.java,這樣一來:

  • 你在檔案總管或 IDE 裡看到 HelloWorld.java,就能立刻知道這個檔案裡面定義的是 HelloWorld 類別。
  • 當你編譯 HelloWorld.java 時,產生的 .class 檔案會是 HelloWorld.class,這樣 JVM 也能按照預期去載入這個類別。

如果不這樣規定,開發者可能會用不相關的檔名,例如 MyFile.java 裡面放 public class HelloWorld,這會讓程式變得難以管理和閱讀。

Java 編譯機制的限制

當 Java 編譯一個 .java 檔案時,它會根據檔案名稱來尋找 public class,並產生對應的 .class 檔案。例如:

// 檔案名稱:HelloWorld.java
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

執行 javac HelloWorld.java 會產生:

HelloWorld.class

如果檔案名稱和 public class 名稱不同,例如:

// 檔案名稱:Test.java
public class HelloWorld {  // 不匹配的類別名稱
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

編譯時會發生錯誤:

Error: Class HelloWorld is public, should be declared in a file named HelloWorld.java

這是因為 Java 編譯器會根據 Test.java 這個檔案名稱,預期找到一個 public class Test,但實際上它卻找到了 public class HelloWorld,導致編譯錯誤。

JVM 載入類別時的要求

當你執行 Java 程式時,JVM 會根據 main 方法所在的類別名稱,去尋找對應的 .class 檔案。例如:

java HelloWorld

這時候 JVM 會去找 HelloWorld.class 這個編譯好的類別。

如果 Java 允許 public class 的名稱與 .java 檔案名稱不同,就可能發生以下問題:

  1. JVM 可能找不到對應的 .class 檔案,因為 .class 檔案的名稱是根據 public class 來決定的,而不是 .java 檔案名稱。
  2. 開發者很容易搞混,例如 java Test 但實際上 Test.class 對應的類別名稱卻是 HelloWorld,導致執行時出錯。

為了避免這種問題,Java 規定 public class 的名稱與 .java 檔案名稱一致,這樣 JVM 就能根據類別名稱正確找到對應的 .class 檔案並執行。


非 public 類別的情況

如果一個 .java 檔案內的類別沒有宣告為 public,那麼這個檔案的名稱可以跟類別名稱不一致。例如:

// 檔案名稱:Test.java
class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

這樣是可以編譯的,因為 HelloWorld 沒有 public,Java 不會強制要求 Test.java 必須跟 HelloWorld 同名。

不過,這時候你不能直接用 java Test 來執行程式,而是要用 java HelloWorld,因為 JVM 會根據 HelloWorld.class 來載入程式。

如果一個 .java 檔案內有多個類別,只能有一個 public 類別,而且檔案名稱必須與這個 public 類別名稱一致。

例如:

// 檔案名稱:MainClass.java
public class MainClass {
    public static void main(String[] args) {
        System.out.println("這是主類別 MainClass");
    }
}

class AnotherClass {
    void sayHello() {
        System.out.println("這是副類別 AnotherClass");
    }
}

這是合法的,因為:

  • MainClass 是 public,所以檔案名稱必須是 MainClass.java。
  • AnotherClass 不是 public,所以它可以有不同的名稱。
  • 執行時只能用 java MainClass,不能用 java AnotherClass。

總結:主類別與 main 方法的必要性

主類別的核心作用

主類別是 Java 程式的 入口點(Entry Point),負責:

  1. 提供 main 方法供 JVM 啟動程式。
  2. 初始化其他物件與邏輯。
  3. 處理輸入/輸出操作。

沒有 main 方法會怎樣?

若嘗試執行以下類別:

class Helper {
    void greet() {
        System.out.println("Hello!");
    }
}

會出現錯誤:

Error: Main method not found in class Helper

public 修飾詞的迷思

主類別 不一定要是 public,只要包含 main 方法即可:

class MainClass { // 非 public 類別
    public static void main(String[] args) {
        System.out.println("執行成功!");
    }
}

但需注意:檔案名稱仍需與類別名稱一致(此例為 MainClass.java)。


常見問題與實戰技巧

快速除錯指南

錯誤類型解決方案
類別名稱與檔案名稱不符檢查 public class 名稱是否正確
缺少 main 方法確認是否定義 public static void main
拼字錯誤(如 String[] args)檢查方法簽名是否完全正確
解決方案檢查 public class 名稱是否正確
解決方案確認是否定義 public static void main
解決方案檢查方法簽名是否完全正確

命名慣例與最佳實踐

  1. 類別名稱使用 大駝峰式命名法(如 MainClass)。
  2. 方法名稱使用 小駝峰式命名法(如 sayHello)。
  3. 檔案名稱與 public class 名稱嚴格一致。
目前還沒有留言,成為第一個留言的人吧!

發表留言

留言將在審核後顯示。

程式語言

目錄

  • Java 程式的基本結構
  • 類別(Class)與方法(Method)
  • 最小可執行程式範例
  • 為什麼 Java 程式一定要從 main 方法開始?
  • 為什麼 main 方法一定要是 static?
  • Java 方法的執行方式
  • JVM 啟動時還沒有物件
  • static 讓 main 可以直接執行
  • 如果 main 不是 static 會發生什麼事?
  • 多個 static 方法不會衝突
  • JVM 只會執行 main 方法
  • main 方法可以主動呼叫其他 static 方法
  • 為什麼 JVM 不能自動建立物件來執行 main?
  • 類別的建構子可能需要參數
  • 類別可能有特殊的初始化邏輯
  • 物件建立可能會影響效能
  • public class 的關鍵作用
  • public class 的定義
  • 檔案名稱的強制規則
  • .class 與 .java 的關係
  • 一個 .java 檔案能產生多個 .class 檔案
  • 如果有 public 類別,檔案名稱必須與 public class 相同
  • 為什麼 public class 的名稱必須與 .java 檔案名稱完全一致?
  • 確保 Java 檔案和類別名稱一致,方便管理與存取
  • Java 編譯機制的限制
  • JVM 載入類別時的要求
  • 非 public 類別的情況
  • 總結:主類別與 main 方法的必要性
  • 主類別的核心作用
  • 沒有 main 方法會怎樣?
  • public 修飾詞的迷思
  • 常見問題與實戰技巧
  • 快速除錯指南
  • 命名慣例與最佳實踐