为什么main方法在java中是静态的

我听过有人说“如果main不是静态的,那么JVM可以创建一个包含main的类对象,并通过对象调用main。
但问题是JVM如何知道在重载构造函数的情况下要调用哪个构造函数,或者即使只有一个参数化的构造函数,然后传递什么。“

这是正确的理由吗?
因为如何在不进入主函数的情况下创建类的对象?
请就此发表意见。 如果这不是正确的理由,那么正确的原因是什么?

这只是一个惯例。 Java语言设计者可以很容易地决定你必须指定一个要实例化的类,使其构造函数成为主要方法。 但是调用静态方法同样有效,并且不需要首先实例化类。

此外,如果类具有超类,则可以通过更改超类来更改程序启动的行为(因为必须在子类之前调用​​超类构造函数),这可能是无意的。 静态方法没有这个问题。

主要方法是静态的,因为它使事情更简单,但如果他们想让它更复杂,他们可以。

“这个理由是对的吗?”

它在某种程度上,虽然从来没有像这样具体解释过。

我们可以让约定也用String...args调用构造函数,这意味着你至少需要一个对象来运行,但(可能)设计者认为不需要它。

例如,有这样的东西没有技术障碍:

  class Hello { public void main(String...args){ System.out.println("Hello, world"); } } 

事实上,如果你没有指定一个构造函数,那么Java会为你创建一个无参数构造函数,如果类包含一个main方法,那么包含一个var args构造函数也很容易,并且在底层创建以下代码:

  class Hello { // created by the compiler public Hello(){} public Hello( String ... args ) { this(); main( args ); } // end of code created by the compiler public void main( String ... args ) { System.out.println("Hello, world!"); } } 

但是这会产生不需要的代码,并且额外分配的对象在这种情况下不会做任何事情; 两个构造函数(而不是一个)等。最后它看起来就像是太多的魔法。

由语言设计师决定。 在这种情况下,他们可能认为不这样做会更简单,只是validation调用的类是否具有名为public static void main( String [] args )的方法的特殊签名

顺便说一句,你可以拥有一个Hello! world 没有main方法的 Java Hello! world程序, 但它抛出java.lang.NoSuchMethodError: main

 public class WithoutMain { static { System.out.println("Look ma, no main!!"); System.exit(0); } } $ java WithoutMain Look ma, no main!! 

我知道它不是另类,但是,有趣的不是吗?

我听过有人说“如果main不是静态的,那么JVM可以创建一个包含main的类对象,并通过对象调用main。

这不是真的。 至少,这在JLS中没有说明。

但问题是JVM如何知道在重载构造函数的情况下要调用哪个构造函数,或者即使只有一个参数化的构造函数,然后传递什么。“

如果是真的,我只是期望它调用(隐式)默认的无参数构造函数。

也可以看看:

  • JLS – 调用main方法

static是一个关键字,当它在main方法之前应用时,JVM将假定这是执行的起点。那么JVM是这样想的吗? java软件给JVM作为通过main()方法EX进入指定类的责任:假设有两个类A和B,其中B扩展A,这里按照java,对于每个类,应该创建一个对象来访问变量和那个类中的方法一样,这里是在类B中写的静态main()方法,静态是单词,无论程序执行开始如何都会在程序执行之前为该关键字分配内存。

因为它可能有主要方法。 而且因为主要对象不需要是一个对象。 如果是,您需要实例化一个。

如果您自己使用jvm.dll,并且只需创建一个对象并调用它,那么您不需要main函数。

但是,通过这种方式,可以进行非面向对象的编程,仅适用于那些因某种原因需要它的人。 🙂

main是静态的,因此您的代码可以执行而无需首先实例化类。 也许你甚至不想创建一个类,或者创建类很慢,你想先打印出一个“Loading …”文本,或者你有多个构造函数等等……有很多原因没有在命令执行开始之前强制用户创建一个类。

如果静态创建对象,则仍可以在执行main()之前创建对象。

是的,在JVM上运行的其他语言创建对象或模块(也是对象)并运行它们。 例如,Fortress语言’Hello world’看起来像

 Component HelloWorld Export Executable run(args) = print "Hello, world!" end 

或者,没有args:

 Component HelloWorld Export Executable run() = print "Hello, world!" end 

Java比纯OO语言更实用,具有静态方法和字段以及原始类型。 它的静态主方法更接近C的主要function。 你不得不问戈斯林他为什么选择这个惯例。

启动JVM的代码非常简单 – 这个示例创建一个JVM,创建一个对象并使用命令行参数调用其run方法 – 创建启动函数(new main.HelloWorld()).run(args)而不是main.HelloWorld.main(args)

 #include  #include  JNIEnv* create_vm() { JavaVM* jvm; JNIEnv* env; JavaVMInitArgs args; JavaVMOption options[1]; args.version = JNI_VERSION_1_2; args.nOptions = 1; options[0].optionString = "-Djava.class.path=C:\\java_main\\classes"; args.options = options; args.ignoreUnrecognized = JNI_TRUE; JNI_CreateJavaVM(&jvm, (void **)&env, &args); return env; } int invoke_class(JNIEnv* env, int argc, char **argv) { jclass helloWorldClass; helloWorldClass = env->FindClass("main/HelloWorld"); if (helloWorldClass == 0) return 1; jmethodID constructorMethod = env->GetMethodID(helloWorldClass, "", "()V"); jobject object = env->NewObject(helloWorldClass, constructorMethod); if (object == 0) return 1; jobjectArray applicationArgs = env->NewObjectArray(argc, env->FindClass("java/lang/String"), NULL); for (int index = 0; index < argc; ++index) { jstring arg = env->NewStringUTF(argv[index]); env->SetObjectArrayElement(applicationArgs, index, arg); } jmethodID runMethod = env->GetMethodID(helloWorldClass, "run", "([Ljava/lang/String;)V"); env->CallVoidMethod(object, runMethod, applicationArgs); return 0; } int main(int argc, char **argv) { JNIEnv* env = create_vm(); return invoke_class( env, argc, argv ); } 

不需要创建一个对象来调用静态方法。 所以jvm不需要分配额外的内存来创建main的obj然后调用它。

但问题是JVM如何知道在重载构造函数的情况下要调用哪个构造函数,或者即使只有一个参数化的构造函数,然后传递什么。“

我也这么认为。 我不使用Java。 我用C ++。 如果您不自己编写构造函数,则会隐式提供默认的无参数构造函数和复制构造函数。 但是当你自己编写构造函数时,编译器不会提供构造函数。 我认为这个理论也得到了Java的遵守。

所以在Class中它不能保证它不会有一个Constructor。 还限制一个类具有用户定义的构造函数是一个坏主意。 但是如果系统允许你编写自己的构造函数,那么即使不能保证它将是无参数构造函数。 所以如果它是一个参数化的构造函数它不知道要发送什么参数。

所以我认为这是静态主要function背后的实际原因。

在java main方法是静态的,Java虚拟机可以调用它而不创建包含main方法的任何类的实例。 如果main方法没有声明为静态,那么JVM必须创建主类的实例,并且因为构造函数可以重载并且可以有参数,所以JVM在Java中找不到主方法也没有任何确定和一致的方法。