为什么Java规范要求程序的主要方法只是无效?
虽然返回类型不是方法签名的一部分,但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规范要求主方法只是无效? 当返回类型不是方法签名的一部分时,为什么会出现此限制?
这个问题不同于为什么java中的main()是无效的? :这个问题因基于意见而被关闭,而我正在寻找JVM调用此方法的代码位置/进程,以及强制它们将此方法保持为空的限制。 他们采取了哪些设计决策(以及背后的推理),以及记录在何处。
我正在寻找事实,以便知道为什么会这样做。 如果不仔细阅读问题的详细信息,请不要将其标记为重复。
PS:退出,是另一回事。 我更关心该计划的进入。 此外,返回的值可能不是使用JVM,而是将其限制为void限制可扩展性。
到目前为止,我从这个问题中学到的是:Java规范已明确修复了返回类型,以避免混淆迁移程序员(C / CPP),他们可能期望此值返回到操作系统,但由于JVM介于此之间,因此该值永远不会返回OS。 为了这个特殊目的(返回OS的值),他们提供了System.exit()方法。
对于那些建议返回类型是签名的一部分的人 – 只需尝试在类中定义以下两种方法
public static void main(String[] a){ } public static String main(String[] a){ }
您将收到编译错误,因为这两种方法的签名是相同的。
main
是void在JLS 12.1.4 Invoke Test.main
指定:
方法
main
必须声明为public
,static
和void
。
有时为什么答案? 因为规范是这么说的 (又名Quod Ego Dixit,或者因为我这么说(Terry Pratchett))。 有时语言设计师的决定是不可用的,我们唯一能做的就是猜测。 这也是明显重复的原因( 为什么java void中的main()? )主要基于意见而被关闭。
现在作为 – 对我来说 – 明显的原因: JLS 12.8程序退出说:
程序会终止其所有活动,并在发生以下两种情况之一时退出:
- 所有不是守护程序线程的线程都会终止。
- 某些线程调用类
Runtime
或类System
的exit
方法,安全管理器不禁止退出操作。
这意味着main
方法的结束并不一定意味着程序的结束。 main
方法的返回码在C语言中具有众所周知的含义:它是进程退出代码。 当main
方法可能在进程本身结束之前很久就退出时,这个含义不适用。
大多数非平凡的Java应用程序通常都是一个短命的主要方法,可以启动一个或多个长期存在的非守护进程线程。 允许来自Java main
方法的返回代码可能意味着实际上并不存在的含义:返回值是进程退出代码。 因此明确指定main
必须具有void返回类型才是好事:它可以减少混淆或分配不存在的含义。
毕竟主要方法可能不是退出点。 由于multithreading,可能会发生当主要返回时,球场上还有另一个线程使程序保持活动状态。 在这种情况下,退出代码没有任何意义。
为什么不虚空?
如果您希望将某些状态返回给OS,则可以使用任何现有方法。最常见的一种是System.exit(int status)
。
如果主要在其他线程之前完成,则返回值无关紧要。 这与c / c ++相反,c / c ++当时不支持multithreading。
像一个挥杆应用程序可能仍然可以在完成主要后在EDT上工作。
如果你还在考虑“入口”点:但返回类型总是谈论退出。
所以它只是无效,因为我们有状态信号在其他情况下返回值或不返回。 但是,没有其他观点,因为它是以这种方式设计的。另一个有不同想法的开发者可能会提出另一个想法来解决同样的情况。取决于。
如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()作为返回点的原因。
您无法从Java Docs中查看以下内容,因为您需要将方法设置为void的主要方法作为退出点。 或者您可以选择在main的末尾显式调用system.exit()。
终止当前运行的Java虚拟机。 该参数用作状态代码; 按照惯例,非零状态代码表示exception终止。
据我所知,
main
方法作为返回类型具有void
的原因是,一旦main
方法完成执行,它并不意味着整个程序完成。 它可能会在场景后面启动并运行一些线程。 即使主线程已经死亡,仍然可能有子线程运行。 在这种情况下, main
的返回类型没有多大意义。
并且JVM
将监视程序完成状态以释放内存,没有必要向JVM
返回一些声明程序已完成的内容。 在C语言中,我们直接与OS通信,因此,有一个选项可以将OS值返回给操作系统,表明执行完成并开始释放内存。 但是在Java中, JVM
将与OS通信而不是程序,所以我们不需要从main返回任何内容。
希望这能清除你的怀疑。
如果你要求JVM运行一个类,java运行库将在你的类中查找到那个签名public static void main(String[] args)
这是你与JVM的契约,如果没有,它将不会执行。 如果要返回int代码,请使用System.exit
控制台程序返回一个int返回码,因此在传统的C程序中, int main(int argc, char** argv)
似乎是合乎逻辑的。
在Java中, exception被引入作为新的控制流机制,并且还模拟或现在实现了multithreading 。 可以使用System.exit(int returnCode)
在任何地方进行退出。
这意味着对main的调用嵌入在一段代码中,除了System.exit
之外,最干净(简约,少例,没有return 0
魔法)是默认返回0。
记住,java旨在强烈地“改进”C,尤其是C ++。 就像使用完全Unicode而不是字节的字符串和字符串一样。
Java被设计为Platform independent language
于Platform independent language
。 因此,如果它的main()
方法返回一个值(如0或1或任何东西),则可以通过不同平台对其进行不同的解释或理解。 因此,与C
和Cpp
不同,它的main()
方法不能返回值。
主要原因是在常见的情况下,特别是在multithreading和GUI应用程序中,您不希望在main中具有返回值。 但是如果真的有这样一个用例,你可以使用exit方法。 这就是你要找的原因。
Java中的主要方法是什么?
Java中的主要方法是任何核心Java程序的入口点。 请记住,我们不是在谈论Servlet,MIDlet或任何其他容器管理的Java程序,其中提供了生命周期方法来控制执行 。 在核心Java程序中,当您键入java main-class-name, JVM搜索该类中的public static void main(String args [])方法时,执行从main方法开始, 如果找不到该方法,则抛出错误NoSuchMethodError :主要和终止。
Java中主要方法的签名
主要方法必须严格遵循其语法; 其他明智的JVM将无法找到它,您的程序将无法运行。 这是main方法的确切签名:
public static void main(String args [])
这个签名是经典签名,从Java开始,但在Java5中引入变量参数或变量,你也可以使用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中是静态的”,有很多原因,但这里有几个理由对我有意义:
-
由于main方法是静态的,因此Java虚拟机可以调用它而无需创建包含main方法的任何类实例。
-
由于C和C ++也有类似的主要方法作为程序执行的入口点,遵循该约定只会帮助Java。
-
如果main方法没有声明为静态,那么JVM必须创建主类的实例,并且因为构造函数可以重载并且可以有参数,所以JVM在Java中找不到主方法也没有任何确定和一致的方法。
-
在Java中的类中声明的任何内容都在引用类型下,并且需要在使用它们之前创建对象,但是静态方法和静态数据被加载到JVM中的单独内存中,称为上下文,这是在加载类时创建的。 如果main方法是静态的,那么它将在JVM上下文中加载并且可以执行。
为什么主要的mehtod在Java中是公开的
Java指定了几个访问修饰符,例如private,protected和public。 在Java中声明为public的任何方法或变量都可以从该类的外部访问。 由于main方法在Java中是公共的,因此JVM可以轻松访问和执行它。
为什么main方法在Java中是无效的
由于Java中的main方法不应该返回任何值,因此它的void表示main并不返回任何值。
概要:
-
主要方法必须在Java中声明为public,static和void,否则JVM将无法运行Java程序。
-
JVM抛出NoSuchMethodException:如果在类中没有找到提供给Java命令的预定义签名的主方法,则抛出main。 例如,如果您运行java Helloworld而不是JVM将在HelloWorld.class文件中搜索public static void main String args [])方法。
-
主方法是任何Core Java程序的入口点。 执行从main方法开始。
4.主要方法由Java中称为“主”线程的特殊线程运行。 您的Java程序将一直运行,直到您的主线程正在运行或从main方法生成的任何非守护程序线程正在运行。
-
当您看到“Thread main中的exception”时,例如Thread main中的exception:Java.lang.NullPointerException意味着在主线程内抛出exception。
-
您可以使用Java 1.5以上的varargs语法声明main方法,例如public static void main(String … args)
-
除了static,void和public之外,您还可以在Java的main方法签名中使用final,synchronized和strictfp修饰符。
- Java中的main方法可以像Java中的任何其他方法一样重载,但JVM只会使用上面指定的指定签名调用main方法。
-
您可以在main方法的签名中使用throws子句,并且可以抛出任何已检查或未检查的exception。
-
甚至在JVM调用main方法之前,就会执行静态初始化程序块。 当JVM将类加载到内存中时执行它们。
我希望这已经回答了你关于主要方法的问题:)
更新以回应:
你的答案有一个小问题:返回类型不是方法签名的一部分。因此,如果返回类型不同,JVM不能抛出exception“NoSuchMethodException:main”。
如果返回类型不同并且返回类型是方法签名的一部分,则它不返回“NoSuchMethodException:main”。 看看这个截图:
我们可以说, main
方法是类启动方法,因为它满足一类启动标准; 请参阅http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4,12.4.1节 –
T是一个类,调用T声明的静态方法。
现在,根据JVM规范, 返回指令用于从声明为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
- PKCS#12:DerInputStream.getLength()exception
- JInternalFrame中的JFreechartexception
- java.lang.IllegalArgumentException:当我使用reflection时,object不是声明类的实例
- 如何在O(N)时间和O(C)空间复杂度中使用Java 8流API从列表中仅删除一个max(min)
- 从Jar重新编译Java类
- 由于新的文件夹结构,在Linux上的Intellij IDEA中正确设置Java 9作为SDK
- Joda时间 – 两个日期之间的月份差异
- 如何在Java中规范化URL?
- 如何检查java类中是否有特定的方法?