Java 无法处理的异常
Java Exceptions that cannot be handled
我经常遇到同样的问题。在我的 Java 应用程序的核心,我有一些方法会抛出任何方法调用者都无法处理的异常。我必须将这些异常冒泡到主要方法。所有这些异常总结,所以我在我的应用程序的更高级别上有很多抛出语句。
例如我的应用程序的核心有一个 NodeJsManager.java class:
public class NodeJsManager {
public static void startNodeJs() throws ExecuteException {
// Code to start NodeJs Server goes here
}
}
要启动 NodeJs 服务器,我必须在命令行上执行一些操作。我可以用 apache class org.apache.commons.exec.CommandLine 做到这一点。但如果执行以错误代码退出,它会抛出 ExecuteException。如果没有启动 NodeJs,我的应用程序将毫无用处。没有任何方法可以捕获此异常,这只是我的应用程序运行的 要求。因此,异常几乎会在整个应用程序生命周期中冒泡。我还有其他执行相同操作的管理器(如果配置路径错误,则抛出异常的 ConfigurationManager)。总之,它在更高级别的每个方法中总结了许多抛出语句,我什至不记得该异常的原因。
你会如何处理这个问题?我必须做一些完全错误的事情,因为我找不到描述我的问题的类似帖子!
问候
麦克
更新
我刚刚发现了我的好旧 有效 Java 书。作者(Google 的 Java 架构师)写了以下关于异常的文章:
... use checked exceptions for recoverable conditions and runtime
exceptions for programming errors.
...
If it isn't clear whether recovery is possible, you're probably better off using an unchecked exception ...
在我的例子中,它显然是不可恢复的,所以抛出运行时异常是可行的方法。我一直认为应该防止运行时异常,这改变了我对 Java.
中异常的看法
我不喜欢检查异常。我以前做的(但这不是一个好的解决方案)是捕获检查的异常并以这种方式将其作为运行时异常重新抛出:
catch (ExecuteException e) {
throw new RuntimeException (e);
}
已检查的异常 "e" 作为参数传递给 RuntimeException。这样,我将已检查的异常转换为未检查的异常。但正如我所说,这不是一个好的解决方案,它可能会导致更多它解决的调试问题。当异常是 "checked" 时,它往往是因为描述的错误是 "serious".
一种解决方案是创建您自己的更通用的异常 class,它将扩展 Exception
并将未处理的异常作为原因包装到您自己的异常中。这样你至少可以减少方法签名的一些异常。示例:
创建新的 class StartupException
或 ConfigurationException
并在启动阶段将其作为原因捕获后将其与主要异常一起抛出。
此外,如果您要 StartupException extends RuntimeException)
,则不必声明此类例外。
另一种方法是将所有内容包装到 RuntimeException
如果abowe不适合您的需求,那么这可能是设计缺陷,(如果您确实无法处理),您将不得不处理它。
一种可能的方法是 Exception
在尽可能靠近它的起源地处理,在那里您有足够的信息来决定要做什么。
正如您所说,如果您在最高级别捕获了所有 Exception
,那么您将失去非常重要的上下文,因为它提供了有关问题发生的原因和方式的信息(希望是修复它的几种方法)。
例如,您说过没有 NodeJS 服务器的应用程序是无用的,那么这样做的一种方法可能是拥有 NodeJSManager
(如果存在这样的东西 :D,我猜)不抛出,而是阻止应用程序启动,比如
NodeJSManager nodejsManager = new NodeJSManager();
boolean succeeded = nodejsManager.tryToStart();
if (!succeeded) {
// guard, it's useless to proceed
// cleanup and exit
}
我调用了那个方法 tryToStart
因为它可能发生服务器没有启动,你正在直接处理可执行文件和文件系统所以我想说这不再那么例外(但可能这只是个人喜好问题)。
恕我直言,重要的是您将应用程序启动指定为一系列检查,例如节点和配置检查,而无需处理 Exception
s 来处理代码流。
我经常遇到同样的问题。在我的 Java 应用程序的核心,我有一些方法会抛出任何方法调用者都无法处理的异常。我必须将这些异常冒泡到主要方法。所有这些异常总结,所以我在我的应用程序的更高级别上有很多抛出语句。
例如我的应用程序的核心有一个 NodeJsManager.java class:
public class NodeJsManager {
public static void startNodeJs() throws ExecuteException {
// Code to start NodeJs Server goes here
}
}
要启动 NodeJs 服务器,我必须在命令行上执行一些操作。我可以用 apache class org.apache.commons.exec.CommandLine 做到这一点。但如果执行以错误代码退出,它会抛出 ExecuteException。如果没有启动 NodeJs,我的应用程序将毫无用处。没有任何方法可以捕获此异常,这只是我的应用程序运行的 要求。因此,异常几乎会在整个应用程序生命周期中冒泡。我还有其他执行相同操作的管理器(如果配置路径错误,则抛出异常的 ConfigurationManager)。总之,它在更高级别的每个方法中总结了许多抛出语句,我什至不记得该异常的原因。
你会如何处理这个问题?我必须做一些完全错误的事情,因为我找不到描述我的问题的类似帖子!
问候 麦克
更新
我刚刚发现了我的好旧 有效 Java 书。作者(Google 的 Java 架构师)写了以下关于异常的文章:
... use checked exceptions for recoverable conditions and runtime exceptions for programming errors.
...
If it isn't clear whether recovery is possible, you're probably better off using an unchecked exception ...
在我的例子中,它显然是不可恢复的,所以抛出运行时异常是可行的方法。我一直认为应该防止运行时异常,这改变了我对 Java.
中异常的看法我不喜欢检查异常。我以前做的(但这不是一个好的解决方案)是捕获检查的异常并以这种方式将其作为运行时异常重新抛出:
catch (ExecuteException e) {
throw new RuntimeException (e);
}
已检查的异常 "e" 作为参数传递给 RuntimeException。这样,我将已检查的异常转换为未检查的异常。但正如我所说,这不是一个好的解决方案,它可能会导致更多它解决的调试问题。当异常是 "checked" 时,它往往是因为描述的错误是 "serious".
一种解决方案是创建您自己的更通用的异常 class,它将扩展 Exception
并将未处理的异常作为原因包装到您自己的异常中。这样你至少可以减少方法签名的一些异常。示例:
创建新的 class StartupException
或 ConfigurationException
并在启动阶段将其作为原因捕获后将其与主要异常一起抛出。
此外,如果您要 StartupException extends RuntimeException)
,则不必声明此类例外。
另一种方法是将所有内容包装到 RuntimeException
如果abowe不适合您的需求,那么这可能是设计缺陷,(如果您确实无法处理),您将不得不处理它。
一种可能的方法是 Exception
在尽可能靠近它的起源地处理,在那里您有足够的信息来决定要做什么。
正如您所说,如果您在最高级别捕获了所有 Exception
,那么您将失去非常重要的上下文,因为它提供了有关问题发生的原因和方式的信息(希望是修复它的几种方法)。
例如,您说过没有 NodeJS 服务器的应用程序是无用的,那么这样做的一种方法可能是拥有 NodeJSManager
(如果存在这样的东西 :D,我猜)不抛出,而是阻止应用程序启动,比如
NodeJSManager nodejsManager = new NodeJSManager();
boolean succeeded = nodejsManager.tryToStart();
if (!succeeded) {
// guard, it's useless to proceed
// cleanup and exit
}
我调用了那个方法 tryToStart
因为它可能发生服务器没有启动,你正在直接处理可执行文件和文件系统所以我想说这不再那么例外(但可能这只是个人喜好问题)。
恕我直言,重要的是您将应用程序启动指定为一系列检查,例如节点和配置检查,而无需处理 Exception
s 来处理代码流。