为什么Java主要方法是静态的?


505

Java main()方法的方法签名为:

public static void main(String[] args){
    ...
}

此方法是否有理由是静态的?


1
在这种情况下,我们不应该说方法签名,因为该术语仅指方法名称及其参数
Andrew Tobilko '16

Java的设计旨在使C程序员熟悉。这与C约定非常接近。
托尔比约恩Ravn的安徒生

Answers:


337

该方法是静态的,因为否则会产生歧义:应调用哪个构造函数?特别是如果您的班级看起来像这样:

public class JavaClass{
  protected JavaClass(int x){}
  public void main(String[] args){
  }
}

JVM应该调用new JavaClass(int)吗?它应该做什么x

如果不是,JVM是否应在JavaClass不运行任何构造方法的情况下实例化?我认为不应该这样做,因为这会使整个类成为特殊情况-有时您有一个尚未初始化的实例,并且必须在每个可以调用的方法中进行检查。

对于JVM来说,在进入入口点之前必须实例化一个类的情况,边缘情况和歧义太多了。这就是为什么main是静态的。

我不知道为什么main总是被标记public


4
实现接口不能解决实例化问题。
Jacob Krall

26
我个人喜欢将其public static void main用作入口点的标记–公共的无参数构造函数不会大喊“这可能是入口点!” 以同样的方式。
雅各布·克拉尔

5
@EdwinDalorzo-强制实例化入口点类会得到什么?调用静态方法对类的负担最小。如果对您的设计更有意义,则可以免费实例化自己。
David Harkness,2012年

18
“应该调用哪个构造函数?” 甚至可以想象一个问题吗?对于main要调用的决策,存在相同的“问题” 。奇怪的是(对您而言),JVM可以很好地进行管理。
康拉德·鲁道夫2012年

9
main方法始终是公共的,因为必须由运行时引擎JVM访问。
gthm

398

这只是约定。实际上,即使名称main()和传入的参数也完全是约定俗成的。

当您运行java.exe(或Windows上的javaw.exe)时,实际上发生了几次Java本机接口(JNI)调用。这些调用将加载真正是JVM的DLL(是的-Java.exe不是JVM)。JNI是我们在桥接虚拟机世界以及C,C ++等世界时使用的工具。反之亦然-至少(据我所知)不可能真正获得JVM在不使用JNI的情况下运行。

基本上,java.exe是一个超级简单的C应用程序,它解析命令行,在JVM中创建一个新的String数组来保存这些参数,解析出指定为包含main()的类名,使用JNI调用来查找main()方法本身,然后调用main()方法,将新创建的字符串数组作为参数传入。这非常类似于使用Java反射时的操作-它只是使用容易混淆的命名本机函数调用。

编写自己的版本的java.exe(源代码随JDK分发)并让它执行完全不同的操作,这是完全合法的。实际上,这正是我们对所有基于Java的应用程序所做的事情。

我们每个Java应用程序都有自己的启动器。我们主要这样做是为了获得自己的图标和进程名称,但是在其他情况下,除了常规的main()调用之外,我们还想做些其他事情以方便处理(例如,在一种情况下, COM互操作性,我们实际上将COM句柄传递给main()而不是字符串数组)。

所以,总之,短期:它是静态的原因是方便的b / c。之所以称其为“ main”,是因为它必须是某种东西,而main()就是他们在C的早期(当时的函数名称重要)所做的事情。我想java.exe可以允许您只指定一个完全限定的主方法名称,而不是仅指定类(java com.mycompany.Foo.someSpecialMain)-但这使IDE很难自动检测“项目中的“可启动”类。


66
+1:非常有趣(尤其是关于编写风俗的部分java.exe
Adam Paynter

9
有趣的是,我确实不同意“这只是约定”。部分答案。OP的主要问题是声明中静态内容的原因。我不认为staticmain()声明只是常规的缘故。它是'main()'而不是其他东西的事实是可行的。
贾里德(Jared)

2
@David做到了。实际上,我更希望从最初参与其中的一个人那里得到一个答案-但这是很遥远的。不幸的是,大多数其他答案都是临时推理中的一种练习。除了不谦虚地避免发明错误的技术细节来推论(可能)非技术原因外,这还提供了非常有趣的细节。
康拉德·鲁道夫2012年

2
@Jared-他们可能需要一个公共的无参数构造函数,并且使其成为main非静态的,并且仍在该语言的范围之内。在不征求设计师意见的情况下,我们只需要同意不同意。:)
David Harkness

4
@BenVoigt您调用LoadLibrary()以获取jvm dll。然后,您调用getprocaddress(“ JNI_CreateJavaVM”),然后调用JNI_CreateJavaVM函数(docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/…)。加载VM后,您可以使用标准JNI调用来查找正确的类,加载静态main方法并调用它。那里没有太多误解的空间。JNI绝对是您加载VM的方式。您可能习惯于使用本地关键字javah -jni等仅编写客户端JNI,但这只是JNI的一半。
凯文·戴

188

main()在方法C++C#Java是静态
因为他们然后可以由运行时引擎调用而不不必实例的任何对象,则代码在身体的main()将完成剩下的。


1
好的,但是运行时不能实例化该类的一个对象吗?然后调用Main方法?为什么?
AndreiRînea,

12
如果您的主类重载了构造函数,JVM将如何知道要调用哪个构造函数?它会通过什么参数?
雅各布·克拉尔

1
@Noah当您说父类时,您的意思是该类包含main方法吗?因为如果是这样,那么“父类”一词在这里会造成混乱,否则对我来说就没有意义。另外,如果按照约定使用public static void main...,为什么不能约定应用程序入口点类应具有公共默认构造函数?
Edwin Dalorzo

2
@Jacob JVM如何知道static void main要调用的重载?完全没有问题。
康拉德·鲁道夫2012年

4
@Namratha:是的,您缺少一些东西。“静态方法不能引用非静态方法”是不正确的。正确的说法是:“使用任何非静态方法时,每个静态方法都必须提供一个对象”。而且,static诸如此类的方法main经常用于new创建这样的对象。
Ben Voigt 2012年

38

为什么公共static void main(String [] 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 main(String... args)

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,其中包含在命令后面的本机C代码java [-options] class [args...]

/*
 * 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);

... ...

4
这里的问题是,这其实是一个非常好的答案,在其原来的形式问题,用大量引用(+1)的。但是,我很想学习将静态方法作为入口点而不是构造函数或实例方法的设计决策的基本原理
Konrad Rudolph

1
@KonradRudolph,关于语言和JVM规范设计方面的问题,也许您可​​以尝试与Oracle的原始资源联系,看看是否可以获得任何积极的反馈。
约克

2
一般而言,当方法结果的计算仅取决于其参数,从而不取决于对象实例的内部状态时,它可以是静态的。为了代码的可维护性/可重用性,建议将其设置为静态。如果该方法main不是静态的,则意味着必须知道类实例状态,并且定义起来要复杂得多,例如首先使用哪个构造函数。
伊夫·马丁

@KonradRudolph有趣的是,Oak(Java的前身)已经要求main方法具有类似的原型:public static void main(String arguments[])-参考:Oak 0.2 Spec
assylias 2012年

2
@Yves 可以。如果另一个设计有意义,则不需要。我在这里的评论中听到了一些很好的论据,但我仍然认为进程实际上非常像一个线程(它),并且Java中的线程通常表示为的实例Runnable。以相同的方式(即具有Runnable.Run入口点)表示整个过程在Java中绝对有意义。当然,Runnable它本身可以说是设计缺陷,这是由于Java还没有匿名方法引起的。但是既然已经在那里……
康拉德·鲁道夫2012年

36

让我们简单地假装,这static不是应用程序入口点所必需的。

应用程序类将如下所示:

class MyApplication {
    public MyApplication(){
        // Some init code here
    }
    public void main(String[] args){
        // real application code here
    }
}

构造函数代码和main方法之间的区别是必要的,因为在OO中,构造函数仅应确保实例已正确初始化。初始化后,该实例可用于预期的“服务”。将完整的应用程序代码放入构造函数中会破坏这一点。

因此,此方法将在应用程序上强制使用三个不同的合同:

  • 必须是一个默认的构造函数。否则,JVM将不知道要调用哪个构造函数以及应提供哪些参数。
  • 必须是一个main方法1。好的,这并不奇怪。
  • 该类不得abstract。否则,JVM无法实例化它。

static另一方面,该方法仅需要一个合同:

  • 必须有一种main方法1

在这里,abstract构造函数都不重要。

由于Java被设计为对用户来说是一种简单的语言因此毫不奇怪,应用程序入口点也已经以一种简单的方式使用一个合约来设计,而不是以复杂的方式使用三个独立且脆弱的合约来设计。

请注意:此参数与JVM或JRE内部的简单性无关。这个论点是关于用户的简单性。


1这里完整的签名仅算作一份合同。


1
实际上,要求更为复杂的:必须有一个main是方法publicstatic以及具有签名void main(String[])。我同意,如果该方法是一个实例方法中,JRE将有略微更多的工作,但这类工作将是相同的,而不是复杂性较高显著(见前面的回答的意见的讨论)。我不认为这种差异说明了将入口点设为静态的决定,尤其是因为存在解决实例方法所需的方法并且易于使用。
康拉德·鲁道夫

3
@KonradRudolph:我的意思不是JRE要做的工作。我的意思是要强迫该语言的每个用户在必要时遵循更多合同。从这个意义上说,一种static public main(String[])方法是一个签名,因此是一个合同。否则,必须遵循三个独立的合同。
2012年

1
啊。我仍然不同意这有什么不同。入口点类可以很好地实现Runnable。显然,Java希望开发人员始终遵守该合同,为什么对于应用程序入口点而言,合同费用太高?这是没有意义的。
康拉德·鲁道夫2012年

3
@KonradRudolph:没有矛盾:在一种情况下,系统将向用户强制执行三份合同。可疑的合同,不能通过编译器检查的合同,并且从用户的角度来看,它们是独立的。在通常ThreadRunnable案件没有什么是对用户隐藏,他可以清楚地看到发生了什么事情,他必须实现的变化只有那些适合他的合同-他是在控制,而不是系统。
2012年

2
这是最好的答案。遗憾的是,许多用户只能阅读页面上的前2或3个答案;而且这个机会不太可能很快到达那里。它提到了构造函数仅用于初始化的要点-因此,以这种构造函数运行整个应用程序的样式进行编码是没有意义的。
达伍德·伊本·卡里姆

14

如果不是,那么如果有多个构造函数,则应使用哪个构造函数?

Java语言规范中提供了有关Java程序的初始化和执行的更多信息。


12

在调用main方法之前,不会实例化任何对象。使用static关键字意味着可以在不首先创建任何对象的情况下调用该方法。


错误。或至少非常不精确。公共类Main {静态Object object = new Object(){{System.out.println(“ object created”); }; 公共静态无效main(String [] args){System.out.println(“ in main”); }
eljenso

公平的评论。从技术上讲,我应该说过,在调用Main方法之前,不会实例化包含main方法的类。
BlackWasp

12

因为否则,它将需要执行对象的实例。但是必须从头开始调用它,而不必首先构造对象,因为通常这是main()函数(引导程序)的任务,通常是通过使用这些参数/程序参数来解析参数并构造对象。


10

让我以更简单的方式解释这些事情:

public static void main(String args[])

除小应用程序外,所有Java应用程序均从开始执行main()

关键字public是一个访问修饰符,它允许从类外部调用成员。

static之所以使用,是因为它可以main()被调用而不必实例化该类的特定实例。

void表示main()不返回任何值。


9

是什么意思public static void main(String args[])

  1. public 是访问说明符,表示任何人都可以访问/调用它,例如JVM(Java虚拟机。
  2. static允许main()在创建类的对象之前调用。这是必需的,因为main()在创建任何对象之前,JVM都会调用它。由于它是静态的,因此可以通过类直接调用。

    class demo {    
        private int length;
        private static int breadth;
        void output(){
            length=5;
            System.out.println(length);
        }
    
        static void staticOutput(){
            breadth=10; 
            System.out.println(breadth);
        }
    
        public static  void main(String args[]){
            demo d1=new demo();
            d1.output(); // Note here output() function is not static so here
            // we need to create object
            staticOutput(); // Note here staticOutput() function is  static so here
            // we needn't to create object Similar is the case with main
            /* Although:
            demo.staticOutput();  Works fine
            d1.staticOutput();  Works fine */
        }
    }

    类似地,我们有时将static用于用户定义的方法,因此我们不需要创建对象。

  3. void指示main()所声明的方法不返回值。

  4. String[] args指定方法中的唯一参数main()

    args-一个包含类类型的对象数组的参数String


6

构造了各种Applet,Midlet,Servlet和Bean,然后在其上调用了生命周期方法。调用main是对main类所做的全部工作,因此不需要将状态保留在多次调用的对象中。将main固定在另一个类上是很正常的(尽管不是一个好主意),这会妨碍使用该类创建主要对象。


5

这只是一个约定,但可能比其他方法更方便。使用静态主程序,调用Java程序所需要做的就是知道类的名称和位置。如果不是静态的,则还必须知道如何实例化该类,或要求该类具有空的构造函数。


这不是约定;它是语言规范的一部分;如果没有静态main方法作为有效入口点,运行时将无法识别该类。
罗布

2
语言规范本身遵循约定。Java设计人员没有实际要求选择使用静态main。但是,正如Logan解释的那样,替代方案更加复杂。
David Arno

@DavidArno说约定遵循语言规范会更有意义。
罗恩侯爵

5

如果main方法不是静态的,则需要从程序外部创建main类的对象。您想怎么做?


5

使用java命令执行Java虚拟机(JVM)时,

java ClassName argument1 argument2 ...

执行应用程序时,如上所述,将其类名称指定为java命令的参数。

JVM尝试调用您指定的类的main方法

—至此,尚未创建该类的对象。

将JVM 声明main为静态allowsinvoke主要without创建instance类。

让我们回到命令

ClassNamecommand-line argumentJVM的,它告诉它要执行哪个类。在ClassName之后,还可以指定list of StringsJVM将传递给您的应用程序的命令行参数(用空格分隔)。-此类参数可能用于指定选项(例如文件名)来运行应用程序-这就是为什么String[] args在main中调用一个参数的原因

参考:Java™如何编程(早期对象),第十版


4

最近,类似的问题已发布在Programmers.SE上

TL; DR接受的答案的一部分是,

在Java中,原因public static void main(String[] args)

  1. 高斯林通缉
  2. 由具有C语言(不是Java)经验的人编写的代码
  3. 由曾经在NeWS上运行PostScript的人执行

http://i.stack.imgur.com/qcmzP.png

 
对于C#来说,推理在传递上相似的。语言设计者使Java程序员熟悉程序入口点语法。正如C#架构师Anders Hejlsberg所说

...我们使用C#的方法只是为Java程序员提供了替代方案...

...


3

我认为关键字“ static”使main方法成为类方法,并且类方法只有一个副本,并且可以被所有人共享,而且它不需要对象作为参考。因此,在编译驱动程序类时,可以调用main方法。(我只是在Java的字母级别,如果我错了,抱歉)


所有方法“都只有一个副本”。
罗恩侯爵,

3

main()是静态的,因为;在应用程序生命周期的这一点上,由于还没有实例化对象,因此应用程序堆栈本质上是过程性的。

这是一块干净的石板。此时,即使没有声明任何对象,您的应用程序仍在运行(请记住,存在过程和OO编码模式)。您作为开发人员,可以通过创建对象实例并根据其中编译的代码将应用程序转换为面向对象的解决方案。

面向对象之所以伟大,有数百万个显而易见的原因。但是,大多数VB开发人员在其代码中定期使用诸如“ goto”之类的关键字的日子已经一去不复返了。“ goto”是VB中的一个过程命令,由其OO对应项:方法调用代替。

您也可以将静态入口点(main)视为纯粹的自由。如果Java具有足够的差异来实例化一个对象,并且仅在运行时向您呈现该实例,那么您将没有选择但是要编写一个过程应用程序。对于Java来说,这是难以想象的,但可能有许多场景需要过程方法。

这可能是一个非常模糊的答复。记住,“类”只是相互关联的代码的集合。“实例”是该类孤立,生活和呼吸自发的一代。


7
这是不正确的。在main达到之前先实例化许多对象。并且,如果在包含main的类中包含静态构造函数,则该构造函数也将main同样执行。
康拉德·鲁道夫2012年

2

这只是一个约定。如果这是约定,那么JVM当然可以处理非静态主方法。毕竟,您可以在类上定义一个静态初始化器,并在进入main()方法之前实例化大量的对象。


2

原型public static void main(String[])JLS中定义的约定:

方法main必须声明为public,static和void。它必须指定一个声明的类型为String数组的形式参数(第8.4.1节)。

在JVM规范5.2中。虚拟机启动我们可以阅读:

Java虚拟机通过使用引导类加载器(第5.3.1节)创建一个初始类来启动,该类以与实现相关的方式指定。然后,Java虚拟机将链接初始类,对其进行初始化,然后调用公共类方法void main(String [])。该方法的调用驱动所有进一步的执行。构成主要方法的Java虚拟机指令的执行可能导致其他类和接口的链接(并因此创建),以及其他方法的调用。

有趣的是,在JVM规范中,没有提到main方法必须是静态的。但是规范还说Java虚拟机在执行以下两个步骤之前:

类或接口的初始化包括执行其类或接口的初始化方法。

2.9。特殊方法

定义了一个类或接口的初始化方法

一个类或接口最多具有一个类或接口初始化方法,并通过调用该方法进行初始化(第5.5节)。类或接口的初始化方法具有特殊名称<clinit>,不带任何参数,并且是无效的。

并且类或接口的初始化方法实例初始化方法的不同之处如下:

在Java虚拟机级别,使用Java编程语言(JLS§8.8)编写的每个构造函数都将显示为具有特殊名称的实例初始化方法<init>

因此,JVM初始化类或接口初始化方法,而不初始化实际上是构造函数的实例初始化方法。因此,他们无需提及JVM规范中main方法必须是静态的,这是因为在调用main方法之前没有创建任何实例这一事实暗示了这一点。


2

public关键字是接入改性剂,它允许程序员控制类成员的可见性。当班级成员前面有public,则可以通过声明该成员的类之外的代码访问该成员。

相反的publicprivate,它防止成员被其类外部定义的代码使用。

在这种情况下,main()必须声明为public,因为启动程序时必须由其类之外的代码调用它。

关键字static允许 main(),而无需实例化的类的特定实例被调用。这是必要的,因为main() Java解释器会在创建任何对象之前调用它。

关键字void只是告诉编译器main()不返回值。


1

任何应用程序的真正入口都是静态方法。如果Java语言支持将实例方法作为“入口点”,则运行时将需要在内部将其实现为静态方法,该方法构造对象的实例,然后调用该实例方法。

鉴于此,我将研究选择以下三个选项之一的基本原理:

  1. 一个static void main()像今天我们看到它。
  2. void main()在新构造的对象上调用的实例方法。
  3. 使用类型的构造函数作为入口点(例如,如果调用了入口类Program,则执行将有效地由组成new Program())。

分解:

static void main()

  1. 调用封闭类的静态构造函数。
  2. 调用static方法main()

void main()

  1. 调用封闭类的静态构造函数。
  2. 通过有效调用构造封闭类的实例new ClassName()
  3. 调用实例方法main()

new ClassName()

  1. 调用封闭类的静态构造函数。
  2. 构造该类的实例(然后不执行任何操作,仅返回)。

理由:

我将按照相反的顺序进行操作。

请记住,Java的设计目标之一是强调(尽可能要求)良好的面向对象编程实践。在这种情况下,对象的构造函数将初始化该对象,但不应对该对象的行为负责。因此,给出了一个切入点的规范new ClassName()将在每个应用程序上强制“理想”构造函数的设计例外,从而使新的Java开发人员困惑。

通过创建main()实例方法,可以解决上述问题。但是,它要求规范列出条目类的构造函数的签名以及main()方法的签名,从而增加了复杂性。

总之,指定a static void main()会创建最复杂的规范,同时遵守将行为放入方法的原则。考虑到实现一个main()本身构造一个类的实例并调用一个实例方法的方法有多简单,将其指定main()为实例方法并没有真正的优势。


1
这只是在乞求问题。Java无论如何都需要一个应用程序加载器,该应用程序加载器在调用之前需要进行大量工作mainmain对于初学者来说过于复杂的理由似乎令人难以置信。事实上,静态main非常适合初学者混乱,我怀疑一个构造函数会更如此。您说“构造函数不应对对象的行为负责”。这听起来很有趣,但我不确定是否会同意。为什么不呢?是什么阻止了这种情况?
康拉德·鲁道夫2012年


1

我不知道JVM是否在实例化对象之前调用了main方法...但是main()方法是静态的却有更强大的原因...当JVM调用类的main方法时(例如,人)。它通过“ Person.main() ” 来调用它。您会看到,JVM通过类名调用它。这就是为什么main()方法应该是静态且公共的,以便JVM可以访问它的原因。

希望能有所帮助。如果有,请通过评论让我知道。


0

静态方法不需要任何对象。它直接运行,因此main直接运行。


0

使用main方法中的静态关键字是因为main方法中没有任何实例化。但是对象是构造的而不是调用的,因此我们在main方法中使用了静态关键字。在jvm上下文中,当类加载到内存中时就会创建内存,并且所有静态成员都存在于该内存中。如果我们现在使主静态成为静态对象,它将在内存中,并且可以由jvm(class.main(..))访问,因此我们无需创建堆就可以调用main方法。


0

正如我们在这里看到的那样,这只是一个约定:

该方法必须声明为public和static,它不能返回任何值,并且必须接受String数组作为参数。默认情况下,第一个非选项参数是要调用的类的名称。应该使用标准的类名。如果指定了-jar选项,则第一个非选项参数是JAR归档文件的名称,其中包含应用程序的类和资源文件,且启动类由Main-Class清单标头指示。

http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/java.html#description


语言的规则,你是说。
罗恩侯爵


0

基本上,我们将那些不执行任何与对象相关的任务的数据成员和成员函数设为静态。在使用main方法的情况下,我们将其作为STATIC,因为它与对象无关,因为main方法始终在运行,无论我们是否创建对象。


0

Java中声明为static的任何方法都属于该类本身。同样,只能通过引用类似的类来访问特定类的静态方法Class_name.method_name();

因此,在访问静态方法之前无需实例化类。

因此main()方法声明为,static因此无需创建该类的对象即可对其进行访问。

由于我们使用存在主方法的类的名称(或程序应从其开始执行的位置)保存该程序的名称,因此适用于不带main()method()(高级)的类。因此,通过上述方式:

Class_name.method_name();

可以访问main方法。

简而言之,在编译程序时,它会在所提及的类中搜索main()具有以下String参数的方法:(main(String args[])在程序的名称中),并且由于在开始时就没有实例化该类的范围,因此main()方法被声明为静态。


它在程序执行而不是编译时发生。
罗恩侯爵

0

java.sun.com(网站上有更多信息):

main方法是静态的,为Java VM解释器提供了一种启动类的方式,而无需先创建控件类的实例。程序启动后,将在main方法中创建控件类的实例。

我的理解一直很简单,就像调用任何静态方法一样,可以在不创建关联类实例的情况下调用main方法,从而使它可以在程序中的其他任何对象之前运行。如果不是静态的,则必须在调用它之前实例化一个对象,这会产生“鸡和蛋”的问题,因为通常在程序开始时主要使用main方法来实例化对象。


但它并没有 “节目中任何事情之前”运行。整个论点都是谬论,而且,这不是提到它的第一个答案,甚至也不是第二个或第三个。
康拉德·鲁道夫

抱歉,我的回答重复了其他人所说的内容;对不起,我只是尽我所能,也只能从网上找到答案。从我查看的结果来看,没有什么其他理由可以说明main方法为何是静态的;除非某个地方深深地藏着,否则也许这是唯一的答案。我对Java的理解是相当基本的,但是我已经听说过上述原因(来自教授,教科书等),而从未听到过。
Jesse M

@Jesse M仅当您甚至不考虑首先阅读其他答案时,您的评论才有意义。顺便说一句,这不是一件遥不可及的事情。正如您自己提到的那样,您的理解是相当基本的,因此很可能其他人已经更熟练地回答了这个问题。为了使您的答案看起来更好,您的评论似乎是合理的。您有Java教科书和教授认为您所主张的内容是一个非同寻常的主张,坦率地说,我不相信他们的主张。(有参考文献吗?)
LeoR

1
@KonradRudolph顶部的评论似乎很合理。main()用作程序的入口点,并且Java网站上有几处参考资料指出,它应该与C / C ++具有main()函数的方式相似。因为Java是所有对象,所以它必须是静态的以避免对象实例化。使其具有静态特性还使其可以在运行时被加载并可执行到JVM中。我只是在反省以前的答案,但我想知道您认为满意的答案是什么。我认为您将获得的最好成绩是“这就是他们想要的方式”。请记住Java的创建日期。
trevor-e 2012年

1
@杰西现场。这完全有可能只是一个约定俗成的问题(尽管我希望不是这样,这将是一个无聊的答案)。我最初对这个问题的兴趣是因为我认为使用Java来使用适当的实例来表示对象“正在运行的应用程序”,并将入口点作为此类的方法(或构造函数),这将是一个更加明显的设计。从一开始就被设计为面向对象的,并且由于RunnableJava中看似相似的对象(线程,通过)确实使用了这种设计。为什么这里有(明显的)例外?
康拉德·鲁道夫2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.