Java主方法的方法签名是:
public static void main(String[] args) {
...
}
为什么这个方法必须是静态的?
Java主方法的方法签名是:
public static void main(String[] args) {
...
}
为什么这个方法必须是静态的?
当前回答
原型public static void main(String[])是在JLS中定义的约定:
方法main必须声明为public、static和void。它必须指定一个形式形参(§8.4.1),其声明类型为String数组。
在JVM规范5.2中。虚拟机启动我们可以读到:
The Java virtual machine starts up by creating an initial class, which is specified in an implementation-dependent manner, using the bootstrap class loader (§5.3.1). The Java virtual machine then links the initial class, initializes it, and invokes the public class method void main(String[]). The invocation of this method drives all further execution. Execution of the Java virtual machine instructions constituting the main method may cause linking (and consequently creation) of additional classes and interfaces, as well as invocation of additional methods.
有趣的是,在JVM规范中并没有提到主方法必须是静态的。 但是规范还说Java虚拟机执行以下两个步骤:
链接初始类(5.4。链接) 初始化它。初始化)
类或接口的初始化包括执行类或接口的初始化方法。
在2.9。特殊方法:
定义一个类或接口初始化方法:
一个类或接口最多有一个类或接口初始化方法,并通过调用该方法进行初始化(§5.5)。类或接口的初始化方法具有特殊名称<clinit>,不带参数,且为空。
类或接口初始化方法不同于定义如下的实例初始化方法:
在Java虚拟机级别,每个用Java编程语言(JLS§8.8)编写的构造函数都作为实例初始化方法出现,具有特殊名称<init>。
因此JVM初始化一个类或接口初始化方法,而不是实例初始化方法,后者实际上是一个构造函数。 因此,他们不需要在JVM规范中提到主方法必须是静态的,因为在调用主方法之前不创建实例这一事实暗示了这一点。
其他回答
这只是惯例。事实上,甚至main()的名称和传入的参数都是纯粹的约定。
当您运行Java .exe(或Windows上的javaw.exe)时,真正发生的是几个Java本机接口(JNI)调用。这些调用加载的DLL是真正的JVM(没错,java.exe不是JVM)。JNI是我们用来连接虚拟机世界和C、c++等语言世界的工具。反过来也是对的——不使用JNI是不可能让JVM运行的(至少据我所知)。
基本上,java.exe是一个超级简单的C应用程序,它解析命令行,在JVM中创建一个新的String数组来保存这些参数,解析出您指定的包含main()的类名,使用JNI调用查找main()方法本身,然后调用main()方法,将新创建的字符串数组作为参数传入。这非常非常类似于您从Java中使用反射时所做的事情——它只是使用了令人混淆的命名本机函数调用。
编写自己版本的java.exe(源代码随JDK一起分发)并让它做一些完全不同的事情是完全合法的。事实上,这正是我们对所有基于java的应用程序所做的。
我们的每个Java应用程序都有自己的启动器。我们这样做主要是为了得到我们自己的图标和进程名,但在其他情况下,当我们想做一些常规的main()调用之外的事情来让事情继续进行时,它也很方便(例如,在一种情况下,我们正在进行COM互操作性,我们实际上将COM句柄传递给main()而不是字符串数组)。
So, long and short: the reason it is static is b/c that's convenient. The reason it's called 'main' is that it had to be something, and main() is what they did in the old days of C (and in those days, the name of the function was important). I suppose that java.exe could have allowed you to just specify a fully qualified main method name, instead of just the class (java com.mycompany.Foo.someSpecialMain) - but that just makes it harder on IDEs to auto-detect the 'launchable' classes in a project.
让我们简单地假设,静态不需要作为应用程序入口点。
一个应用程序类看起来是这样的:
class MyApplication {
public MyApplication(){
// Some init code here
}
public void main(String[] args){
// real application code here
}
}
构造函数代码和主方法之间的区别是必要的,因为在OO中,构造函数只应确保实例被正确初始化。初始化后,实例可以用于预期的“服务”。将完整的应用程序代码放到构造函数中会破坏这一点。
因此,这种方法将在应用程序上强制执行三个不同的契约:
必须有一个默认构造函数。否则,JVM将不知道调用哪个构造函数以及应该提供哪些参数。 必须有一个主要的方法。好吧,这并不奇怪。 类不能是抽象的。否则,JVM无法实例化它。
另一方面,静态方法只需要一个契约:
必须有一个主要的方法。
这里抽象构造函数和多重构造函数都不重要。
由于Java被设计为一种简单的语言,所以应用程序入口点被设计为使用一个简单的契约,而不是使用三个独立而脆弱的契约,这并不奇怪。
请注意:这个参数不是关于JVM或JRE内部的简单性。这个参数是关于用户的简单性。
在这里,完整的签名只能算作一份合同。
public静态void关键字意味着Java虚拟机(JVM)解释器可以调用程序的主方法来启动程序(public),而无需创建类的实例(static),并且程序结束时不会将数据返回给Java VM解释器(void)。
来源: 要领,第1部分,第2课:构建应用程序
如果不是,如果有多个构造函数,应该使用哪个构造函数?
在Java语言规范中有更多关于Java程序初始化和执行的信息。
如果主方法不是静态的,则需要从程序外部创建主类的对象。你想怎么做呢?