漫畫:程序員太難了!爲什麼 Java 中的 main 方法必須是它?

作者 | 漫話編程

來源 | 漫話編程(ID:mhcoding)

在 Java 中,想必所有人都不會對 main 方法感到陌生,main 方法是 Java 應用程序的入口方法。程序運行時,要執行的第一個方法就是 main 方法。

在使用 Java 寫下第一個 hello world 的時候,我們需要創建一個 main 方法,當我們使用 Spring Boot 啓動一個 web 應用的時候,我們也同樣需要一個 main 方法。

當我們在 Intellij IDEA 中想要創建 main 方法的時候,只需要輸入 psvm 就會自動幫忙創建一個 main 方法:

我們得到一個 main 方法後,不知道你有沒有發現,任何時候,我們要創建的 main 方法的形式都是一樣的:

public static void main(String[] args) {
}

首先都是 public 的、都是 static 的,返回值都是 void,方法名都是 main,入參都是一個字符串數組。

以上的方法聲明中,唯一可以改變的的部分就是方法的參數名,你可以把 args改成任意你想要使用的名字。

當然,main 方法還可以寫成以下形式,不過其實沒啥區別:

public static void main(String... args) {
}

那麼,不知道大家有沒有想過,爲什麼 main 方法必須得是 public static void 類型的,他的參數又必須得是一個字符串數組呢?

Java 虛擬機如何啓動


在《Java 語言規範》中,對於 Java 虛擬機的啓動給出了明確的定義:Java 虛擬機是通過加載指定的類,然後調用該類中的 main 方法而啓動的。

也就是說,通過調用某個指定類的 main 方法,傳遞給他單個的字符串數組參數,就可以啓動 Java 虛擬機。

一個 main 方法想要被執行,需要經過幾個步驟,首先對應的類需要被虛擬機加載,然後需要進行鏈接和初始化、之後纔是調用 main 方法。

那麼一個方法想要被調用,根據它的訪問限定符以及方法類型不同,被調用的條件也是不同的。

爲什麼 main 方法是公有的(public)?


Java 中,可以使用訪問控制符來保護對類、變量、方法和構造方法的訪問。Java 支持 4 種不同的訪問權限。

default (即默認,什麼也不寫): 在同一包內可見,不使用任何修飾符。使用對象:類、接口、變量、方法。

private : 在同一類內可見。使用對象:變量、方法。注意:不能修飾類(外部類)

public : 對所有類可見。使用對象:類、接口、變量、方法

protected : 對同一包內的類和所有子類可見。使用對象:變量、方法。注意:不能修飾類(外部類)。

以上四種控制符都可以用來修飾方法,但是被修飾的方法的訪問權限就不同了。

而對於 main 方法來說,我們需要通過 JVM 直接調用它,那麼就需要它的限定符必須是 public 的,否則是無法訪問的。

爲什麼 main 方法是靜態的(static)?


static 是靜態修飾符,被他修飾的方法我們稱之爲靜態方法,靜態方法有一個特點,那就是靜態方法獨立於該類的任何對象,它不依賴類特定的實例,被類的所有實例共享。只要這個類被加載,Java 虛擬機就能根據類名在運行時數據區的方法區內定找到他們。

而對於 main 方法來說,他的調用過程是經歷了類加載、鏈接和初始化的。但是並沒有被實例化過,這時候如果想要調用一個類中的方法。那麼這個方法必須是靜態方法,否則是無法調用的。

爲什麼 main 方法沒有返回值(void)?


如果大家對於 C 語言和 C++語言有一定的瞭解的話,就會知道,像 C、C++ 這種以 int 爲 main 函數返回值的編程語言。

這個返回值在是程序退出時的 exit code,一般被命令解釋器或其他外部程序調用已確定流程是否完成。一本正常情況下用 0 返回,非 0 爲異常退出。

而在 Java 中,這個退出過程是由 JVM 進行控制的,在發生以下兩種情況時,程序會終止其所有行爲並退出:

1、所有不是後臺守護線程的線程全部終止。

2、某個線程調用了 Runtime 類或者 System 類的 exit 方法,並且安全管理器並不禁止 exit 操作。

上面的兩種情況中,第二種情況一旦發生,JVM 是不會管 main 方法有沒有執行完的,它都會終止所有行爲並退出,這時候 main 方法的返回值是沒有任何意義的。

所以,main 方法的返回值就被固定要求爲 void。

爲什麼 main 方法的入參是字符串數組(String[])


Java 應用程序是可以通過命令行接受參數傳入的,從命令行傳遞的參數可以在java 程序中接收,並且可以用作輸入。

因爲命令行參數最終都是以字符串的形式傳遞的,並且有的時候命令行參數不止一個,所以就可能傳遞多個參數。

這時候,作爲 Java 應用程序執行的入口,main 方法就需要能夠接受這多個字符串參數,那麼就使用字符串數組了。

總結


main 方法是 JVM 執行的入口,爲了方便 JVM 調用,所以需要將他的訪問權限設置爲 public,並且靜態方法可以方便 JVM 直接調用,無需實例化對象。

因爲 JVM 的退出其實是不完全依賴 main 方法的,所以 JVM 並不會接收 main 方法的返回值,所以給 main 方法定義一個返回值沒有任何意義。所以 main 方法的返回值爲 void。

爲了方便 main 函數可以接受多個字符串參數作爲入參,所以它的形參類型被定義爲 String[]。

更多精彩推薦
☞不愧是你!Python 之父退休太無聊,進微軟搞開源!
☞行業 AI 落地新範式,華爲雲下午茶等你來聊知識計算
☞華爲定義5.5G網絡;阿里巴巴美股投資者發起集體訴訟;Kaldi核心算法K2 0.1版本發佈|極客頭條
☞64歲Python之父退休失敗,正式加入微軟搞開源

☞如何破解“中國開源拿來主義”?包雲崗的幾點分析
☞2020年,區塊鏈和加密領域的女性數量激增
點分享點點贊點在看
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章