漫画:程序员太难了!为什么 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年,区块链和加密领域的女性数量激增
点分享点点赞点在看
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章