Java的System.exit(0);与C++的return 0;有何区别?

18

在学校学习C++时,我们的教授会告诉我们要在主函数的最后一行编写return 0;,这被视为良好的编程实践。

然而,在Java中,我发现有些人在主方法的最后一行编写System.exit(0);

但是,在C++中,如果我使用exit(0);我会被我的教授扣分,因为(在学校里)对于过程性编程,我们期望让程序流动到main的结尾并让程序自然停止。

我的问题:Java的System.exit(0);是否类似于C++的return 0;?(还是类似于C++的exit(0)

在Java中使用System.exit(0)是否不必要时(即在主方法的最后一行编写它)是一种不良实践吗?


2
这是相当情境化的,作为一个“老派”的开发者,我被教导函数和方法只有一个入口点和一个出口点,但这同样适用于System.exit。在你的代码中使用它的问题与在函数/方法中使用多个return语句相同,它们很容易被忽略,使理解代码更加困难。话虽如此,每个规则都有例外,有些项目可能需要在运行程序时终止它...但我仍然会寻找避免它的方法... - MadProgrammer
1
我从未在主方法的最后一行使用 System.exit(0); - earthmover
就像C++一样,另一个是默默地添加进去的。 - Elliott Frisch
也许这个问题可以帮助解释:https://dev59.com/IHA65IYBdhLWcg3wogIb - Matt Coubrough
在Java中,System.exit(0);等同于C语言中的exit(0);。在Java中,return;或者return 0;等同于C语言中的return;或者return 0;exit会关闭整个进程,而return只是退出子程序或函数。 - Smeterlink
显示剩余2条评论
5个回答

19

System.exit(0)在Java中与C++中的exit(0)类似,因为:

  • 它终止了进程
  • 可以从程序任何位置调用。

后一点使它成为“非结构化”控制流结构,学术界倾向于不赞同。(在这种情况下,他们有一个很好的理由:如果一个函数通过异常(或老式的返回代码)报告失败,调用者可能会从错误中恢复,但exit会烧毁这座桥梁。当然,有时错误确实需要被视为致命的。)

在C ++中,如果return 0main函数中,则相当于exit(0)(在其他函数中,它没有特殊含义。)

这里C ++和Java之间的相关不同是main的返回类型。

  • 在C ++中,main必须返回int。通常,这意味着它必须有一个return语句,但C ++标准将main作为一种特殊情况,如果您不编写return语句,则有一个隐含的return 0;作为结束。
  • 在Java中,main必须返回void

在C ++中,通常会在main中编写return语句,即使它在技术上是多余的,也是为了与程序中所有其他非void函数的风格一致。

在Java中,您不能从main返回退出代码,因为它是一个void函数。因此,如果要明确指定退出代码,则必须使用System.exit

每个Java main函数以System.exit(0)结尾并不是错误的,但除非您有像下面这样的结构,否则这样做并不习惯用语。

public static void main(String[] args) {
   try {
       //... do the work
       System.exit(0);
   } catch (Throwable t) {
       //... report the error
       System.exit(1);
   }
}

11
如果您的应用程序使用非守护线程运行时间比主线程的生命周期更长,那么以 exit 结束 main 方法是错误的。 - Darkhogg
@Darkhogg,那么在Java中设置退出代码的正确方式是什么?首先加入所有非守护线程,然后再调用exit(1)函数? - Cruncher
不退出(0)会影响RAII吗?在主函数中打开的文件/套接字等可能无法正确刷新其输出。 - josefx
@josefx:Java没有RAII。文件/套接字等必须显式关闭。(尽管,最近版本的语言有一个try-with-resources结构,类似于C#的using,使这个过程更加方便。) - dan04
@dan04 我想我是在使用 c++ 中的 main 方法时引用了 exit(0)。在 main 方法中使用 exit(0) 可能会阻止静态对象的析构函数运行,这可能会导致未刷新的文件、套接字等问题。 - josefx

9
在Java中,System.exit(0), System.exit(1), System.exit(-1)用于判断程序的执行情况。当程序正常执行时,使用0;当出现错误时,可以使用1, -1或其他非零值,并根据不同类型的错误使用不同的值。
也可以这样说: 0表示一切正常; 1表示我预期会出错的事情出错了; -1表示我没有预料到的问题出错了。 Java Doc中提到:
参数作为状态码;按照惯例,非零状态码表示异常终止。

Java的System.exit(0);和C++的return 0;类似吗?

是的,它们都很相似。

在Java中,如果不必要,使用System.exit(0)是否是一种不好的做法?

我不会说这是一种不好的做法,但是你应该知道何时使用它以及在哪里使用它。您可以使用它通过退出代码为命令行工具抛出错误而不是抛出异常。System.exit(0)终止JVM,因此您应该非常确定何时使用它。

一个例子:

try {  
    runTheWholeApplication();  
    System.exit(0);  // Signifying the normal end of your program
} catch (Throwable t) {  
    reportErrorSomehow(t);  
    System.exit(1);  // Signifying that there is an error
}

所以我认为它的作用类似于C++的exit(0)。那么除非我们正在编写带有线程等内容的程序,否则可能应该避免使用它? - user3437460
2
@user3437460 是的,它是同一件事。 - Elliott Frisch
1
在POSIX系统上,退出代码是一个8位无符号整数。你可以返回-1,但它会被解释为255(由于二进制补码)。 - dan04

4
在学校学习C++时,教授会告诉我们在主函数的最后一行写上return 0;,这被视为良好的编程实践。但这是有争议的。他是否也告诉过你,在main中,return 0;是隐式的?个人而言,我从不在main中编写冗余的return 0;,在其他人的代码中也几乎看不到它。

6
我这么做是因为我学的是 C89,如果你不指定的话,它可以从 main 函数返回非零值:https://dev59.com/Kmcs5IYBdhLWcg3wVyil。 - pjc50

3
是的。Java中的System.exit(0);是一个直接的类比,因为原型Java main方法定义为:
public static void main(String[] args) {
}

所以它实际上无法返回一个int(尽管它可以简单地return;)。在C++中,你可以使用exit(0);,这也是等效的。

...那么return;呢? - earthmover
1
@AnkitLamba 编辑过了。是的,你可以简单地 return - Elliott Frisch

3
原始操作系统Unix在很大程度上依赖于使用和组合许多小程序的命令行脚本。程序的返回代码用于控制流程。返回代码0表示一切正常,非零表示错误。
因此,在C语言中,int main(...)是直接映射,而末尾的return 0;是合适的。退出就像抛出异常,绕过任何返回。它还禁止从另一个程序调用main函数。
在Java中,public void main(...)这个过程被简化了,0是隐含的。System.exit(0);有相同的错误假设,即没有其他程序调用main函数。虽然void反映了99%的使用情况,但现在对于非零错误代码,System.exit(...);是不可避免的。
这也必须被视为更一般的设计决策;C严重依赖于函数的返回代码,这使得控制流程变得困难或容易出错,而Java引入了异常的使用作为可能强制性的控制流程,并提供了自由选择的catch。现在,System.exit(13)的替代方案可能是throw new IllegalArgumentException("Unlucky");。

你的看法是,是否在Java main的最后一行使用System.exit(0)是不好的实践? - user3437460
1
@user3437460:不,这不是一个坏习惯。我可以举个例子,比如当你编写批处理或shell脚本时,脚本运行的每个程序都有一个退出错误代码。通常情况下,如果错误代码为零,则无需采取任何措施,但如果错误代码为非零,则可能需要编写一个例程来处理它,即使它只是过早退出。因此,在这种情况下,使用System.exit()并不是一个坏主意。 - user3414693
是的,多余的工作,比如 x = x;return;。请注意,对于使用这些返回代码的程序,它可能被视为文档:一个提示。 - Joop Eggen
@JoopEggen 感谢您的回复,您的解决方案比其他人更加深入。+1 - user3437460
2
@user3437460 你也是对的;但是JVM程序正常退出时确实会返回0,因此不需要显式地编写它;就像在void函数的末尾编写return;一样,这是一个不确定的程序员的标志。但正如上面所说,这可能是一种风格,列出所有的System.exit(...) - Joop Eggen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接