漫話:為什麼Java中的main方法必須是public static void的?

2021-02-15 漫話編程

在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虛擬機是通過加載指定的類,然後調用該類中的main方法而啟動的。

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

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

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

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

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

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

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

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

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

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

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

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

如果大家對於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[]。

相關焦點

  • 為什麼Java的main方法必須是public static void?
    ,你是否曾經想過為什麼 main 方法是 public、static、void 的。當然,很多人首先學的是 C 和 C++,但是在 Java 中 main 方法與前者有些細微的不同,它不會返回任何值,為什麼 main 方式是 public、static、void,這篇文章嘗試去找到一些答案。
  • 今天終於搞懂了:為什麼Java的main方法必須是public static void?
    Java 程式語言時知道的第一個方法,你是否曾經想過為什麼 main 方法是 public、static、void 的。當然,很多人首先學的是 C 和 C++,但是在 Java 中 main 方法與前者有些細微的不同,它不會返回任何值,為什麼 main 方式是 public、static、void,這篇文章嘗試去找到一些答案。
  • 你搞懂了嗎:為什麼 Java 的 main 方法必須是 public static void?
    當然,很多人首先學的是 C 和 C++,但是在 Java 中 main 方法與前者有些細微的不同,它不會返回任何值,為什麼 main 方式是 public、static、void,這篇文章嘗試去找到一些答案。
  • 今天終於搞懂了:為什麼 Java 的 main 方法必須是 public static void?
    Java 程式語言時知道的第一個方法,你是否曾經想過為什麼 main 方法是 public、static、void 的。當然,很多人首先學的是 C 和 C++,但是在 Java 中 main 方法與前者有些細微的不同,它不會返回任何值,為什麼 main 方式是 public、static、void,這篇文章嘗試去找到一些答案。
  • 為什麼 main 方法是 public static void ?
    Java程式語言時知道的第一個方法,你是否曾經想過為什麼main方法是public、static、void的。當然,很多人首先學的是C和C++,但是在Java中main方法與前者有些細微的不同,它不會返回任何值,為什麼main方式是public、static、void,這篇文章嘗試去找到一些答案。
  • public static void main(String[] args)方法詳解
    ,比如方法的名字必須是main,方法必須是publicstatic void 類型的,方法必須接收一個字符串數組的參數等等。在看Java中的main()方法之前,先看一個最簡單的Java應用程式HelloWorld,我將通過這個例子說明Java類中main()方法的奧秘,程序的代碼如下:publicclass HelloWorld {    public static void main(String[] args) {        System.out.println
  • 10個經典的 Java main 方法面試題
    但是,在引進變參時,你可以將字符串類型的變參作為參數傳遞給main()方法。變參一定得是數組。package com.instanceofjava;public class MainMethod{public static void main(String args[]){}}3.我們能不能改變main()方法的返回類型?
  • Java中的static關鍵字解析
    因此,如果說想在不創建對象的情況下調用某個方法,就可以將這個方法設置為static。我們最常見的static方法就是main方法,至於為什麼main方法必須是static的,現在就很清楚了。因為程序在執行main方法的時候沒有創建任何對象,因此只有通過類名來訪問。
  • 「原創」為什麼java中一切都是對象,還要有static?
    1. static的「由來」咱們先來分析一下以下代碼:public class Demo {public static void main(String[] args) { //實例化一個p1
  • Java之static關鍵字修飾成員方法
    各位小夥伴們大家好,這次小編要講的是Java當中,關鍵字static修飾成員方法的一些作用。關於成員方法,小編在之前的文章中有過介紹,大家可以去看java之類的定義和對象的創建及使用。在成員方法中一旦使用關鍵字static修飾,那麼就變成了靜態方法,靜態方法不屬於對象,屬於類。
  • JAVA中synchronized與static synchronized 的區別
    一個日本作者-結成浩的《java多線程設計模式》有這樣的一個列子: pulbic class Something(){     publicsynchronizedvoid isSyncA(){}     publicsynchronizedvoid isSyncB(){}     publicstaticsynchronizedvoid
  • Java學習進階-Stream流
    搭建好函數模型才會執行, 其中函數模型必須包含終結方法 終結方法: 方法返回值類型不為Stream流的方法. 非終結方法: 方法返回值類型依然是Stream流的方法.2. Stream流不能重複操作.3. Stream流中不能存儲數據.4. Stream流的操作不會影響數據源數據.
  • Java什麼情況要使用static修飾
    通常情況下,類成員必須通過它的類的對象訪問,但是可以創建這樣一個成員,它能夠被它自己使用,而不必引用特定的實例。在成員的聲明前面加上關鍵字static(靜態的)就能創建這樣的成員。如果一個成員被聲明為static,它就能夠在它的類的任何對象創建之前被訪問,而不必引用任何對象。你可以將方法和變量都聲明為static。static 成員的最常見的例子是main() 。
  • 50個常見的 Java 錯誤及避免方法(第二部分)
    「Cannot Return a Value From Method Whose Result Type Is Void」當一個void方法嘗試返回值時,就會發生此Java錯誤,例如在以下示例中:public static void move(){ System.out.println("What do you want to do?")
  • Java之戳中痛點之 synchronized 深度解析|java|override|author|...
    {static SynchronizedTest2 st = new SynchronizedTest2();  public static void main(String[] args) {Thread t1 = new Thread(st);Thread t2 = new Thread(st);t1.start();t2.start();
  • Java中的static關鍵字和靜態變量、靜態方法
    publicstatic void main(String[] args) { // TODO Auto-generated method stub Ball b1=new Ball();//創建第一個圓形對象 Ball b2=new Ball();//創建第二個圓形對象
  • Java反射機制深入詳解
    import java.lang.reflect.*; public class DumpMethods { public static void main(String args[]) { try { Class c = Class.forName("java.util.Stack"); Method m[] = c.getDeclaredMethods(); for (int i
  • 淺談Java中的hashcode方法
    如果要判斷兩個對象是否真正相等,必須通過equals方法。二.equals方法和hashCode方法在有些情況下,程序設計者在設計一個類的時候為需要重寫equals方法,比如String類,但是千萬要注意,在重寫equals方法的同時,必須重寫hashCode方法。為什麼這麼說呢?
  • Java 中的 6 顆語法糖
    /*** 在原始碼中存在泛型*/public static void main(String[] args) { Map<String,String> map = new HashMap<String,String>(); map.put("hello","你好"); String hello
  • Java 中的異常和處理詳解
    package com.example;import java. util .Scanner ;public class AllDemo{      public static void main (String [] args )      {            System . out. println