为什么Java规范要求程序的主要方法仅为空?

时间:2015-06-30 05:28:42

标签: java jvm return-type

虽然返回类型不是方法签名的一部分,但JVM查找的确切声明为

 public static void main(String[] args)

我的假设是,因为方法签名没有"返回类型"包括在内,我一定是 允许更改返回类型。

但是,如果我将其更改为public static int main(String[] args)并返回一个值,假设为0,则JVM无法执行该程序并退出并显示错误

Error: Main method must return a value of type void in class TestData, please 
define the main method as:
   public static void main(String[] args)

为什么Java规范要求主方法仅为空? 当返回类型不是方法签名的一部分时,为什么会出现这种限制?

这个问题与Why is main() in java void?不同:这个问题因基于意见而被关闭,而我正在寻找JVM调用此方法的代码位置/进程,以及强制的限制是什么他们要保持这种方法无效。他们采取了哪些设计决策(以及背后的推理),以及记录在哪里。

我正在寻找事实,以便知道为什么会这样做。 请不要在没有详细说明问题的情况下将其标记为重复。

PS:退出,是另一回事。我更关心该计划的进入。此外,返回的值可能不是使用JVM,而是将其限制为无限制可扩展性。

到目前为止,我从这个问题中学到的是:Java规范明确地修复了返回类型,以避免混淆迁移程序员(C / CPP),他们可能期望这个值返回到OS,但是因为JVM介于此之间值永远不会返回给操作系统。出于这个特殊目的(返回OS的值),他们提供了System.exit()方法。

对于那些建议返回类型是签名的人 - 只是尝试在类中定义以下两种方法

    public static void main(String[] a){

    }
    public static String main(String[] a){

    }

您将收到编译错误,因为这两种方法的签名都是相同的。

12 个答案:

答案 0 :(得分:21)

main

中指定了main无效
  

方法public必须声明为staticvoidexit

有时为什么?的答案是,因为规范是这样的(又名Quod Ego Dixit,或者因为我这么说(Terry Pratchett))。有时语言设计师的决定是不可用的,我们唯一能做的就是猜测。这也是明显重复(JLS 12.1.4 Invoke Test.main)主要基于意见的原因。

现在作为 - 对我来说 - 显而易见的原因:Why is main() in java void?说:

  

程序会终止其所有活动,并在发生以下两种情况之一时退出:

     
      
  • 所有不是守护程序线程的线程终止。
  •   
  • 某个线程调用类Runtime或类System的{​​{1}}方法,安全管理器不会禁止退出操作。
  •   

这意味着main方法的结束并不一定意味着程序的结束。来自main方法的返回码在C语言中具有众所周知的含义:它是进程退出代码。当main方法可能在进程本身结束之前很久就退出时,此含义不适用。

大多数非平凡的Java应用程序通常都是一个短命的主方法,可以启动一个或多个长期存在的非守护程序线程。允许来自Java main方法的返回代码可能意味着实际上并不存在的含义:返回值是进程退出代码。因此,明确指定main必须具有void返回类型才是好事:它可以减少混淆或分配不存在的含义。

答案 1 :(得分:18)

主要方法毕竟可能不是退出点。由于多线程,可能会发生当主要返回时,球场上还有另一个线程使程序保持活动状态。在这种情况下,退出代码没有任何意义。

答案 2 :(得分:12)

为什么无效?

如果您希望将某些状态返回给操作系统,则可以使用任何现有方法。最常见的方法是System.exit(int status)

如果您的主要在其他线程之前完成,则返回值无关紧要。 这与当时不支持多线程的c / c ++形成对比。

就像一个挥杆应用程序在完成main之后仍然可以在EDT上工作。

如果你还在考虑“入口”点:但返回类型总是谈论退出。

所以它只是无效,因为我们有状态信号器来返回值或在其他情况下没有返回。 但是,没有其他观点,因为它是以这种方式设计的。另一个有不同想法的开发者可能会提出另一个想法来解决同样的情况。取决于。

答案 3 :(得分:8)

如上所述 http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.8

  

12.8。程序退出

     

程序终止其所有活动,并在两件事之一时退出   发生的情况:

     

所有不是守护程序线程的线程都会终止。

     

某些线程调用Runtime类或类System的exit方法,   并且安全管理员不禁止退出操作。

如果所有正在运行的线程都是deamon,程序将退出。因此,如果您有非deamon线程,main方法可能会在程序结束之前返回。

程序的生命周期可以延长main方法的生命周期,返回的数字可能会在程序的后期决定。

我认为这就是他们使用System.exit()作为返回点的原因。

答案 4 :(得分:5)

您无法从Java Docs中查看以下内容,因为您需要将方法设置为void的主要方法作为退出点。或者您可以选择在main的末尾显式调用system.exit()。

  

终止当前运行的Java虚拟机。该参数用作状态代码;按照惯例,非零状态代码表示异常终止。

答案 5 :(得分:5)

据我所知,

main方法作为返回类型的void方法的原因是,一旦main方法完成执行,它并不意味着整个程序已完成。它可能会在场景后面启动并运行一些线程。即使主线程已经死亡,仍然有可能运行子线程。在这种情况下,main的返回类型没有多大意义。

并且JVM将监视程序完成状态以释放内存,没有必要返回指示程序完成的JVM。在C语言中,我们直接与O.S.沟通。所以,有一个选项可以将int值返回给O.S.表明执行完成并开始释放内存。但是在java中,JVM将与O.S.进行通信。但不是程序,所以我们不需要从main返回任何东西。

希望这可以解除你的怀疑。

答案 6 :(得分:4)

如果你要求JVM运行一个类,java运行库将在你的类public static void main(String[] args)中查找该签名 那是你与JVM的合约,如果没有,它将不会执行。 如果要返回int代码,请使用System.exit

答案 7 :(得分:4)

控制台程序返回一个int返回码,因此在传统的C程序中,int main(int argc, char** argv)似乎是合乎逻辑的。

在Java中,异常作为新的控制流机制引入,并且还模拟或现在实现了多线程。可以使用 System.exit(int returnCode) 在任何地方退出。

这意味着对main的调用嵌入在一段代码中,而且最简洁,更少的情况,没有return 0的魔力)是默认返回0,除了System.exit

介意,java旨在强烈“改进”C,尤其是C ++。就像使用完全Unicode而不是字节的字符串和字符串一样。

答案 8 :(得分:2)

Java被设计为Platform independent language。因此,如果它的main()方法返回一个值(如0或1或任何东西),则可以通过不同的平台对其进行不同的解释或理解。因此,与CCpp不同,它的main()方法无法返回值。

答案 9 :(得分:2)

主要原因是在常见的情况下,特别是在多线程和GUI应用程序中,您不希望在main中具有返回值。但是,如果你真的有这样一个用例,你可以使用exit方法。这就是你要找的原因。

答案 10 :(得分:1)

  

Java中的主要方法是什么?

Java中的主要方法是任何核心Java程序的入口点。请记住,我们没有谈论Servlet,MIDlet或任何其他容器管理的Java程序,其中提供了生命周期方法来控制执行。在核心Java程序中,当您在该类中键入java main-class-name, JVM搜索public static void main(String args [])方法时,执行将从main方法开始,如果是,则执行没有找到那个方法抛出错误NoSuchMethodError:main 并终止。

Java中主要方法的签名

主要方法必须严格遵循其语法;其他明智的JVM将无法找到它,您的程序将无法运行。这是主要方法的确切签名:

public static void main(String args [])

这个签名是经典签名,从Java开始,但在Java5中引入变量参数或varargs,你也可以使用varargs语法在Java中声明main方法,如下例所示:

public static void main(String ... args)

记住varargs版本的java main方法只能在Java 1.5或更高版本中使用。除了public,static和void之外,还有一些关键字,如final,synchronized和strictfp,这些关键字在java main方法的签名中是允许的。

  

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

为什么main方法是JavaNow中的public static void来到主要观点"为什么main方法在Java中是静态的?#周围有很多原因,但这里有几个理由对我有意义:

  1. 由于main方法是静态的,因此Java虚拟机可以调用它而无需创建包含main方法的任何类实例。

  2. 由于C和C ++也有类似的主要方法作为程序执行的入口点,遵循该约定只会有助于Java。

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

  4. 在Java中的类中声明的任何内容都在引用类型下,并且需要在使用它们之前创建对象,但静态方法和静态数据被加载到JVM中的单独内存中,称为上下文,这是在加载类时创建的。如果main方法是静态的,那么它将在JVM上下文中加载并且可以执行。

  5.   

    为什么主要的mehtod在Java中是公开的

    Java指定了几个访问修饰符,例如私人,受保护和公共。可以从该类外部访问在Java中声明为public的任何方法或变量。由于主要方法是公开的 Java,JVM可以轻松访问和执行它。

      

    为什么main方法在Java中是无效的

    由于Java中的main方法不应返回任何值,因此它的void表示main并不返回任何值。

    要点:

    1. 主要方法必须在Java中声明为public,static和void,否则JVM将无法运行Java程序。

    2. JVM抛出NoSuchMethodException:main如果它没有找到提供给Java命令的类中预定义签名的主要方法。例如。如果运行java Helloworld而不是JVM将在HelloWorld.class文件中搜索public static void main String args [])方法。

    3. 主要方法是任何Core Java程序的入口点。执行从main方法开始。

    4. <强> 4。主方法由一个名为&#34; main&#34;的特殊线程运行。 Java中的线程。您的Java程序将一直运行,直到您的主线程正在运行或从main方法生成的任何非守护程序线程正在运行。

      1. 当你看到&#34; Thread main中的异常时“例如 Thread main中的异常:Java.lang.NullPointerException这意味着在主线程内抛出了异常。

      2. 您可以使用Java 1.5中的varargs语法声明main方法,例如 public static void main(String ... args)

      3. 除了static,void和public之外,您还可以在Java的main方法签名中使用final,synchronized和strictfp修饰符。

      4.   
            
        1. Java中的主要方法可以像Java中的任何其他方法一样重载,但JVM只会调用指定了指定签名的main方法   上方。
        2.   
        1. 您可以在main方法的签名中使用throws子句,并且可以抛出任何已检查或未检查的异常。

        2. 即使在JVM调用main方法之前,也会执行静态初始化程序块。它们在JVM将类加载到Memory中时执行。

        3. 我希望这已经回答了关于主要方法的问题:)

          更新以回应:

            

          你的回答有一个小问题:回归类型不是其中的一部分   方法签名..因此,JVM不能抛出异常   &#34; NoSuchMethodException:主&#34;如果返回类型不同。

          它没有返回&#34; NoSuchMethodException:main&#34;如果返回类型不同并且返回类型是方法签名的一部分。看一下这个截图:

          enter image description here

答案 11 :(得分:-1)

我们可以说main方法作为类启动方法,因为它满足了一个类启动标准;请参阅http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4 12.4.1 部分 -

T是一个类,调用T声明的静态方法。

现在,根据JVM规范, return 指令用于从声明为void的方法,实例初始化方法,和类或接口初始化方法返回。 http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.11.8

请在此处查看有关退货说明的详细信息:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.10.1.9.return