如果我有一个程序调用了引发异常的方法,该方法必须在抛出特定异常时终止,我是否应该设计该程序,以便将该异常传递回main以便可以安全地返回,或者应该在函数中处理该异常 并调用System.exit(-1)?
这是我在函数中处理它的意思的示例:
public class MyClass{
public static void main (String[] args){
myFunction(args);
}
public static void myFunction(String[] args){
try{
if(args.length == 0)
throw Exception("Invalid Input");
}catch(Exception e){
System.out.println(e);
System.exit(-1);
}
}
}
这是我所说的意思的一个例子:
public class MyClass{
public static void main (String[] args){
try{
myFunction(args);
}catch(Exception e){
System.out.println(e);
}
}
public static void myFunction(String[] args) throws Exception{
if(args.length == 0)
throw Exception("Invalid Input");
}
}
在这种情况下应使用哪种方式?
如果您只允许从main()捕获未引发的异常,则程序将终止。为什么要捕获异常致命的异常?另外,catch(Exception e){ System.exit(-1); }通常从来都不是一个好主意。
这是由于输入无效而引发的异常,这对程序不是致命的,但要求我退出程序。
好的,如果您实际上共享一些相关代码,那就更好了。
@MickMnemonic实际的代码很长,因此我修改了示例,以使其代表我的情况。我退出的原因是,如果在示例中输入不正确,程序将无法继续。
我得说..这是我一段时间以来最聪明/最发人深省的问题之一。
请阅读为什么对"最佳实践"提出疑问是一件坏事?在尝试提出更多基于观点的问题之前,这些问题会引起争论性的讨论,因为它们没有一个统一的答案。
主要基于意见-许多好的问题会基于专家的经验而产生一定程度的意见,但是对这个问题的答案往往几乎完全基于意见,而不是事实,参考资料或特定的专业知识。请阅读我应该避免问哪些类型的问题?在尝试提出更多问题之前。
正如我的回答所表明的那样,这个问题在本质上并不是主要基于观点,并且有一个基于技术理由的答案。
对我来说,这是一个非常棘手的问题,我现在只想分享一些想法。
您需要注意两个主要因素:
致命吗?您能防止它破坏/关闭程序吗?
你能做些例外吗?记录一些有用的信息?通过某些方法还原它?
1号
如果它是致命的,那么您最好尝试在适当的层中捕获程序exit,以确保它正常运行,也许是在抛出异常或更高异常的地方(取决于2号);
2号
如果您想跟踪一些有用的信息以进行调试甚至恢复(如果可能)。
然后,是否捕获它并在哪里处理取决于您的项目/系统。
以正常情况为例:
如果需要在调用层中跟踪信息,则应在较低层中捕获异常,并引发异常以使调用层/较高层具有该异常:
记录一些有用的信息进行调试
或通过其他方法将其恢复(例如,您已引入策略专利,也许您应该尝试其他策略来替代当前策略来处理同一工作);
另一个词
请不要尝试将exception引入您的项目/系统逻辑,exception应该被视为处理意外问题的异常。
很抱歉添加此内容,希望对您有所帮助。
可以以某种方式回答这个问题,从本质上讲,它不是主要基于意见的问题。
首先,考虑相关的问题"什么时候应该抛出异常"?正确的答案是"如果且仅当备选方案将是无法建立发布条件或保持不变"。这提醒我们要考虑方法发布条件。您提供了一个用于解析命令行参数的方法的示例。该命令的发布条件应为"命令行参数有效"。因此,如果命令行参数无效,则该规则告诉我们该方法应引发异常,而不必终止。
其次,考虑为什么根本没有例外。有没有它们的编程语言(特别是C)。替代方法是使用状态代码。异常的优点之一是,它们将对问题(在引发异常的地方)的检测与确定在出现问题(在其中捕获异常)的情况下的处理方式分开。它们为上级调用方法提供了"向上推策略"的方法。因此,如果出现问题(例如您的示例中的无效命令行参数),程序应该终止吗?这是一个政策问题,因此属于较高级别的方法,而不属于较低级别的方法。同样的论点适用于程序的所有级别:没有任何方法可以证明终止程序,实施最严厉的策略是合理的,因为它可以通过引发异常将策略向上推。不能向上推策略的唯一方法是main方法,因为它没有向上推策略的调用者。这表明只有main方法才应导致程序终止。请注意,JVM是以这种方式运行的:即使根本无法处理的虚拟机错误也应该导致程序终止,导致抛出VirtualMachineError而不是直接终止程序。
几乎没有理由致电System.exit。也许在某些灾难性的情况下,您想立即停止JVM,很难想象会是什么。因此,我想说,在没有某些非常具体的要求的情况下,切勿调用System.exit。
在main方法中设置一个try-catch块,捕获Throwable并将其记录下来。这样可以最大程度地减少程序其他地方的异常处理,并鼓励采用一种快速失败的编程方式,以免异常被吞噬和丢失。
另外,也许您有一个通过Shell脚本运行的小型Java程序。您可以让main方法抛出exception并让Shell脚本调用者将stderr重定向到文件。但是使用真实的记录器可以更好地控制滚动和清除等操作。
如果您担心会引发一些无法记录的错误(也许我们内存不足,并且无法在没有引起另一个内存不足错误的情况下进行记录),除了拥有Java外,还应将记录添加到调用方程序会做自己的日志记录,以防万一。
因此,由于我需要在这里退出,因此建议您将其传递回main以记录错误并安全返回?
@ user1939991:通常是。 您想要避免的是在源程序附近发现一些异常,在该源程序中现在程序处于不良状态,从那里继续执行只会导致更多错误。 您可以使用异常将控制权移至安全的地方。
从这篇文章:
You should catch the exception when you are in the method that knows what to do.
如果抛出异常的方法知道如何处理错误,则应该处理该错误。否则,如果该方法不知道如何处理该异常,则应将其抛出。
在您的问题中,由于您希望在发生异常时退出程序,因此将异常返回给main方法可能很有意义。
这篇文章也有一些很好的信息。