这是否是正确的原因?因为如果没有进入main函数,怎么能创建类的对象呢?请发表您的观点。如果这不是正确的原因,那么正确的原因是什么呢?
这是否是正确的原因?因为如果没有进入main函数,怎么能创建类的对象呢?请发表您的观点。如果这不是正确的原因,那么正确的原因是什么呢?
这只是一种惯例。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!");
}
}
但这样会产生不必要的代码和额外分配的对象,在这种情况下不会有任何作用;两个构造函数(而不是一个)等。最终看起来就像太多的魔法。
这取决于语言设计者。在这种情况下,他们可能认为不这样做更简单,只需验证被调用的类是否具有名为public static void main(String[] args)
的方法的特殊签名。
顺便说一下,你可以在Java中有一个没有main方法的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!!
我知道这不是一个替代方案,但是,这还是很有趣的,不是吗?
static是一个关键字,当它被应用在main方法之前时,JVM会认为这是程序执行的起点。为什么JVM会这样想呢?这是因为Java开发人员将责任交给JVM通过main()方法进入指定的类。 例如:假设有两个类A和B,其中B扩展了A,在Java中,对于每个类都应该创建一个对象以访问该类中的变量和方法。在类B中编写了静态的main()方法,静态关键字表示无论程序执行何时,它都将分配内存给该关键字。
是的,其他运行在JVM上的语言会创建对象或模块(也是对象),并运行它们。例如,Fortress语言的“Hello world”看起来像:
Component HelloWorld
Export Executable
run(args) = print "Hello, world!"
end
或者没有参数:
Component HelloWorld
Export Executable
run() = print "Hello, world!"
end
Java比纯面向对象的语言更加实用,具有静态方法和字段以及原始类型。它的静态主方法更接近于C的主函数。你可以问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 );
}
因为可以有主方法。而且主对象不需要是一个对象。如果是这样的话,你需要实例化一个。
如果你为自己使用jvm.dll,并创建一个对象并调用它,那么你就不需要一个主函数。
然而,以这种方式进行非面向对象编程是可能的,只是为了那些出于某种原因需要这样做的人。 :)
main函数是静态的,因此您的代码可以在不必先实例化类的情况下执行。也许您甚至不想创建一个类,或者创建类很慢,您想先打印出“正在加载…”文本,或者您有多个构造函数等等…有很多原因不要强制用户在命令执行之前创建一个类。
如果您以静态方式创建对象,则可以在main()执行之前创建它们。
我也这样认为。我不使用Java,我使用C ++。如果您没有自己编写构造函数,则会隐式提供默认无参数构造函数和复制构造函数。但是当您自己编写构造函数时,编译器不会提供任何构造函数。我认为Java也遵循这个理论。
因此,在类中不能保证不会有构造函数。同时,限制类不具有用户定义的构造函数是一个坏主意。但是,如果系统允许您编写自己的构造函数,则甚至没有保证它将是无参数构造函数。因此,如果它是参数化构造函数,则不知道要发送什么参数。
因此,我认为这就是静态Main函数背后的实际原因。