Java主方法的方法签名是:
public static void main(String[] args) {
...
}
为什么这个方法必须是静态的?
Java主方法的方法签名是:
public static void main(String[] args) {
...
}
为什么这个方法必须是静态的?
当前回答
这只是一种惯例。JVM当然可以处理非静态的主方法,如果这是惯例的话。毕竟,您可以在类上定义静态初始化器,并在到达main()方法之前实例化无数对象。
其他回答
使用Java命令运行Java虚拟机(JVM)时,
java ClassName argument1 argument2 ...
当您执行您的应用程序时,您指定它的类名作为java命令的参数,如上所述
JVM尝试调用您指定的类的主方法
-在这一点上,类的对象还没有被创建。 将main声明为静态允许JVM在不创建的情况下调用main 类的实例。
让我们回到命令
ClassName是JVM的命令行参数,它告诉JVM要执行哪个类。在ClassName之后,您还可以指定一个字符串列表(由空格分隔)作为JVM将传递给应用程序的命令行参数。-这些参数可以用来指定运行应用程序的选项(例如文件名)-这就是为什么在main中有一个名为String[] args的参数
参考资料:Java™如何编程(早期对象),第十版
Static表示该方法是类方法。并且调用时不需要任何类的对象。
The main method of the program has the reserved word static which means it is allowed to be used in the static context. A context relates to the use of computer memory during the running of the program. When the virtual machine loads a program, it creates the static context for it, allocating computer memory to store the program and its data, etc.. A dynamic context is certain kind of allocation of memory which is made later, during the running of the program. The program would not be able to start if the main method was not allowed to run in the static context.
该方法是静态的,否则就会产生歧义:应该调用哪个构造函数?特别是如果你的类是这样的:
public class JavaClass{
protected JavaClass(int x){}
public void main(String[] args){
}
}
JVM是否应该调用新的JavaClass(int)?x应该通过什么?
如果不是,JVM是否应该实例化JavaClass而不运行任何构造函数方法?我认为不应该这样,因为那样会使你的整个类出现特殊情况——有时你有一个没有初始化的实例,你必须在每个可能被调用的方法中检查它。
在调用入口点之前,JVM必须实例化一个类,这有太多的边缘情况和模糊性,因此没有意义。这就是为什么main是静态的。
我不知道为什么main总是被标记为public。
为什么公共静态无效主(字符串[]args) ?
这就是Java语言和Java虚拟机是如何设计和编写的。
Oracle Java语言规范
请参阅第12章执行- 12.1.4节调用Test.main:
最后,在完成Test类的初始化之后(在此期间可能发生了其他相应的加载、链接和初始化),调用Test的main方法。 方法main必须声明为public、static和void。它必须接受一个字符串数组的参数。此方法可以声明为任意一种 public static void main(String[] args) 或 public static void mainargs)
Oracle Java虚拟机规范
请参阅第2章Java编程语言概念-第2.17节执行:
Java虚拟机通过调用某个指定类的main方法并向其传递一个参数(字符串数组)来开始执行。这将导致指定的类被加载(§2.17.2),链接(§2.17.3)到它使用的其他类型,并初始化(§2.17.4)。方法main必须声明为public、static和void。
Oracle OpenJDK源代码
下载并提取jar源代码,看看JVM是如何编写的,查看../launcher/java. C,其中包含java [-options] class [args…]命令背后的原生C代码:
/*
* Get the application's main class.
* ... ...
*/
if (jarfile != 0) {
mainClassName = GetMainClassName(env, jarfile);
... ...
mainClass = LoadClass(env, classname);
if(mainClass == NULL) { /* exception occured */
... ...
/* Get the application's main method */
mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
"([Ljava/lang/String;)V");
... ...
{ /* Make sure the main method is public */
jint mods;
jmethodID mid;
jobject obj = (*env)->ToReflectedMethod(env, mainClass,
mainID, JNI_TRUE);
... ...
/* Build argument array */
mainArgs = NewPlatformStringArray(env, argv, argc);
if (mainArgs == NULL) {
ReportExceptionDescription(env);
goto leave;
}
/* Invoke main method. */
(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
... ...