Java GUI应用程序中引发的未检查异常

Java GUI应用程序中引发的未检查异常,java,exception-handling,Java,Exception Handling,我们知道,未经检查的例外情况将用于违反方法契约的情况。如果应用程序在控制台中运行,则异常将与堆栈跟踪一起出现在控制台窗口中。即使是从控制台调用的GUI应用程序(比如用Swing编写的),并且控制台是在后台运行的,也是如此 但是,如果GUI应用程序没有控制台,会发生什么?例如,用户双击链接,应用程序直接启动,后台没有任何控制台。未经处理的未检查异常将走向何方 这个问题的原因是一些开发人员试图根据上述场景证明捕获未经检查的异常是合理的。如果抛出异常,通常会转到标准输出,如果控制台或管道不存在,操作系

我们知道,未经检查的例外情况将用于违反方法契约的情况。如果应用程序在控制台中运行,则异常将与堆栈跟踪一起出现在控制台窗口中。即使是从控制台调用的GUI应用程序(比如用Swing编写的),并且控制台是在后台运行的,也是如此

但是,如果GUI应用程序没有控制台,会发生什么?例如,用户双击链接,应用程序直接启动,后台没有任何控制台。未经处理的未检查异常将走向何方


这个问题的原因是一些开发人员试图根据上述场景证明捕获未经检查的异常是合理的。

如果抛出异常,通常会转到标准输出,如果控制台或管道不存在,操作系统会忽略标准输出

我认为GUI线程抛出的异常(无法进入控制台)会被彻底丢弃。他们哪儿也去不了

此外,未经检查的例外情况肯定不一定“在违反方法合同的情况下使用”。在这个问题上有很多争议——何时使用检查和未检查的异常,为什么,为什么您会或不想捕获异常,等等。在考虑调用其他库、调用Java库等时,这一点更加复杂。您可能还想对未检查的异常做些什么。(例如,Java的Number类中的解析方法抛出您几乎肯定想要捕获的未检查异常。)

我总是在某个地方从GUI线程捕获未经检查的异常,因为显示有用的对话框比在控制台上显示异常更方便用户。例外情况针对的是开发人员,而不是用户。在Java中,有一种特殊的机制来实现这一点,它允许您捕获所有GUI异常,并在它们进入控制台之前对它们进行一些有建设性的处理。您可以调用
Thread.setDefaultUncheckedExceptionHandler()
来设置处理所有线程中未检查异常的默认方法,还可以调用
System.setProperty(“sun.awt.exception.handler”,“命名异常处理程序类的字符串”)
,以便系统将异常传递给您选择的类。据我所知,这两个类都需要实现
Thread.UncaughtExceptionHandler


编辑:要归功于AKF和其他人,他们确实去了stderr。问题是,启动GUI应用程序的典型方法不涉及将stderr重定向到文件;stderr和stdout被丢弃了。我强烈建议您使用某种类型的日志记录工具,然后进行日志记录,不仅记录异常,还记录代码中发生的其他有趣的事情。例如,我为我的一些研究代码设置了一个原始的日志记录工具,以便它在启动某些算法代码时进行记录,记录需要多长时间,记录在哪个实验案例上,等等。但是对于生产代码,我可能想花些时间学习和使用一个真正的日志记录工具,如log4j,
java.util.logging
,这些未经检查的异常仍将写入stderr。因此,将stderr(和stdout)重定向到一个文件非常有用。

在OS X上,GUI应用程序中的错误消息会附加到系统日志中,可在控制台应用程序中查看。我不知道这是否是专门针对Java应用程序中的异常而发生的,但我想是这样的,如果您有任何异常,那么测试起来都很容易

我不知道其他的操作系统


我同意其他海报的观点,即您应该自己将它们重定向到一个文件。

正如其他人所提到的,未经检查的异常将转到stderr,当没有控制台时,它将不起作用。最好的办法是记录异常,然后向用户显示错误消息。请注意,异常处理程序可以安装在所有线程上,也可以安装在特定线程上,例如UI线程。

请小心-EDT将其所有分派调用包装在一个try/catch块中(这会将它们转移到stderr),因此,尽管您可以在EDT上注册异常处理程序,但它永远不会被调用。有一种在EDT上注册处理程序的机制(尽管它不是标准的或官方的)-如果这很重要,发布一个响应,我将在我们的内部库中挖掘我们是如何做到这一点的。实际上,如果您查看java.awt.EventDispatchThread.processException()的源代码,您将看到只要“sun.awt.exception.handler”属性,则该异常将被重新调用并与任何其他异常一样处理。唯一需要注意的是,如果您处于模态对话框中,在这种情况下,它们会放弃并转储到stderr。