为啥main方法在java中是静态的[重复]
Posted
技术标签:
【中文标题】为啥main方法在java中是静态的[重复]【英文标题】:Why main method is static in java [duplicate]为什么main方法在java中是静态的[重复] 【发布时间】:2011-03-12 00:09:24 【问题描述】:我听到有人说“如果 main 不是静态的,那么 JVM 可以创建一个对象 包含 main 的类并通过对象调用该 main。 但问题是 JVM 如何知道在构造函数重载的情况下调用哪个构造函数,或者即使只有一个参数化构造函数,然后传递什么。”
这是正确的原因吗? 因为不进入主函数怎么创建类的对象呢? 请就此发表您的看法。如果这不是正确的原因,那么正确的原因是什么?
【问题讨论】:
【参考方案1】:这只是一个约定。 Java 语言设计者可以很容易地决定您必须指定一个要实例化的类,使其构造函数成为主要方法。但是调用静态方法同样有效,并且不需要先实例化一个类。
另外,如果该类有一个超类,您可以通过更改超类来改变程序启动的行为(因为必须在子类之前调用超类构造函数),这可能是无意的。静态方法没有这个问题。
主要方法是静态的,因为它使事情变得更简单,但如果他们想让它更复杂,他们可以做到。
【讨论】:
Java以C为蓝本,Java的“main”概念与C的“main”概念非常接近。【参考方案2】:“这个理由对吗?”
在某种程度上是这样,尽管从未如此具体地解释过。
我们可以约定也使用String...args
调用构造函数,这意味着您至少需要一个对象来运行,但(可能)设计者认为不需要。
例如,有这样的东西没有技术障碍:
class Hello
public void main(String...args)
System.out.println("Hello, world");
事实上,Java 会为你创建一个无参数构造函数,如果你不指定一个,那么也很容易包含一个 var args 构造函数,如果该类包含一个 main 方法,并在下创建引擎盖下面的代码:
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!");
但这会创建不需要的代码,以及额外分配的对象,在这种情况下不会做任何事情;两个构造函数(而不是一个)等等。最后它看起来太神奇了。
取决于语言设计者。在这种情况下,他们可能认为不这样做会更简单,只需验证调用的类是否具有称为public static void main( String [] args )
的方法的特殊签名
顺便说一句,您可以在 Java 中使用 Hello! world
程序 without main method,但它会抛出 java.lang.NoSuchMethodError: main
public class WithoutMain
static
System.out.println("Look ma, no main!!");
System.exit(0);
$ java WithoutMain
Look ma, no main!!
我知道这不是一个替代方案,但有趣的是不是吗?
【讨论】:
【参考方案3】:我听说有人说“如果 main 不是静态的,那么 JVM 可以创建一个包含 main 的类的对象并通过对象调用该 main。
这不是真的。至少,这在JLS 中没有指定。
但问题是 JVM 如何知道在构造函数重载的情况下调用哪个构造函数,或者即使只有一个参数化构造函数,然后传递什么。”
如果是真的,我只希望它调用(隐式)默认的无参数构造函数。
另见:
JLS - Invoke main method【讨论】:
我希望它使用 this(String... args) 构造函数。 好的..我只是想问一下JVM是否有可能在任何情况下创建一个包含main的类对象?如果可以创建对象,是否可以通过它调用main?请举个例子。 (几乎)一切皆有可能。但是 JVM 目前没有这样做,jvm/java 规范也没有说应该这样做。 不,它没有。您需要您自己(在main()
方法中)完成。
@Pete:我根据 JLS 给出了答案。责备我,因为这在技术上并非不可能,老实说没有意义:)【参考方案4】:
static是一个关键字,当它应用在main方法之前时,JVM会假设这是执行的起点。所以你的JVM是这样想的吗? java软人赋予JVM负责通过main()方法进入指定类 前任: 假设有两个类 A 和 B, 其中 B 扩展 A, 这里根据java,对于每个类都应该创建一个对象来访问该类中的变量和方法,这里在B类中编写了静态main()方法,静态是单词,不管程序执行是否开始......它将被分配程序执行前该关键字的内存。
【讨论】:
【参考方案5】:因为它可能有主要方法。并且因为主要对象不需要是对象。如果是,则需要实例化一个。
如果你自己使用jvm.dll,你不需要main函数,只需创建一个对象并调用它。
但是,通过这种方式,可以进行非面向对象的编程,只是为了那些出于某种原因需要它的人。 :)
【讨论】:
【参考方案6】:main 是静态的,因此您的代码无需先实例化类即可执行。也许您甚至不想创建一个类,或者创建类很慢并且您想先打印出“正在加载...”文本,或者您有多个构造函数等...有很多原因不强制用户在开始执行命令之前创建一个类。
如果您静态创建对象,您仍然可以在执行 main() 之前创建对象。
【讨论】:
【参考方案7】:是的,在 JVM 上运行的其他语言会创建对象或模块(它们也是对象)并运行它们。例如,堡垒语言“Hello world”看起来像
Component HelloWorld
Export Executable
run(args) = print "Hello, world!"
end
或者,没有参数:
Component HelloWorld
Export Executable
run() = print "Hello, world!"
end
Java 比纯 OO 语言更实用一些,它具有静态方法和字段以及原始类型。它的静态 main 方法更接近于 C 的 main 函数。您将不得不询问 Gosling 他为什么选择该公约。
启动 JVM 的代码相当简单 - 这个例子创建了一个 JVM,创建了一个对象并使用命令行参数调用它的 run
方法 - 使启动函数 (new main.HelloWorld()).run(args)
而不是 main.HelloWorld.main(args)
:
#include <stdio.h>
#include <jni.h>
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, "<init>", "()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 );
【讨论】:
【参考方案8】:不需要创建对象来调用静态方法。所以jvm不需要分配额外的内存来创建main的obj然后调用它。
【讨论】:
【参考方案9】:但问题是 JVM 如何知道在构造函数重载的情况下调用哪个构造函数,或者即使只有一个参数化构造函数,然后传递什么。”
我也这么认为。我不使用Java。我使用 C++。如果您不自己编写构造函数,则默认为您提供无参数构造函数和复制构造函数。但是当您自己编写构造函数时,编译器不会提供构造函数。我认为 Java 也遵循了这个理论。
所以在一个类中它不能保证它不会有一个构造函数。还限制类具有用户定义的构造函数是一个坏主意。但是,如果系统允许您编写自己的构造函数,那么即使不能保证它将是无参数构造函数。所以如果是带参数的构造函数就不知道要送什么参数了。
所以我认为这就是静态 Main 函数背后的真正原因。
【讨论】:
以上是关于为啥main方法在java中是静态的[重复]的主要内容,如果未能解决你的问题,请参考以下文章