当我们需要抛出自定义异常时,如何防止异常捕获?
How to prevent exception catching when we need to throw custom exceptions?
void connectOverNetwork() throws Exception {
try {
final JSONObject response = make network call;
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new Exception("message replied with error");
}
} catch (final Exception e) {
LOG.error("---- bar message ---");
throw new SvcException("failed to connect over network");
}
}
在上面的代码中,我抛出了一个带有失败消息的异常。
同时,我也报了网络连接失败的错误。
但是,如果我为 !success
抛出异常,它会再次被捕获,导致重复记录。如果我只想记录 foo message
.
,我不想打印 bar message
如何预防?
验证 try-catch
语句后的 response
。
JSONObject response = null;
try {
response = /* make network call */;
} catch (final Exception e) {
LOG.error("---- bar message ---");
throw new SvcException("failed to connect over network");
}
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new Exception("message replied with error");
}
我不建议捕获 Exception
- 它太笼统了,我建议您将其缩小到更具体的异常类型。
如果将它移到 try
块之外怎么办。无论如何,第一个 try..catch
的原因是要捕获来自网络调用的任何异常。
JSONObject response = null;
try {
response = make network call;
} catch (final Exception e) {
LOG.error("---- bar message ---");
throw new SvcException("failed to connect over network");
}
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new Exception("message replied with error");
}
创建您自己的异常类型并且不捕获它。
try {
do stuff
if (condition)
throw new MyCustomException("error")
} catch (IOException e) {
log and rethrow
}
首先,让我指出您代码中的一个错误。您的方法声明它抛出异常,但它没有。它抛出 SvcException。所以这就是 "throws" 子句应该说的。 (无论如何你都不应该说 "throws Exception" 。你应该明确说明它抛出的异常类型。)其余的答案取决于你的模糊描述 "make network call" 是否抛出异常。
如果没有,您的方法应如下所示:
void connectOverNetwork() throws SvcException {
final JSONObject response = makeNetworkCall();
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new SvcException("message replied with error");
}
}
但这不现实。很有可能,您的 "make network call" 代码会抛出类似 IOException 的异常。在这种情况下,您的代码应如下所示:
void connectOverNetwork() throws SvcException {
try {
final JSONObject response = makeNetworkCall(); // throws IOException
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new SvcException("message replied with error");
}
} catch (final IOException e) {
LOG.error("--- foo message ---");
throw new SvcException("failed to connect", e); // wrap e inside SvcException
}
}
请注意,我将捕获的 IOException 包装在 SvcException 中。如果您的 SvcException 不这样做,要么重写它以便它可以,要么在抛出它之前调用它的 initCause()
方法。在重新抛出不同的异常时,您应该始终包含原始异常。
另请注意,我没有费心抛出,然后捕获并重新抛出 IOException。当我检测到故障时。我只是抛出我需要抛出的异常。这意味着我需要在两个不同的地方记录 foo 消息。对于大多数事情,应该避免重复一行代码,但是对于日志记录,这很好。
但是这段代码有点乱。我会通过将成功测试与可能的 IOException 分开来清理它。所以我会这样写:
void connectOverNetwork() throws SvcException {
JSONObject response; // no need to initialize this.
try {
response = makeNetworkCall(); // throws IOException
} catch (final IOException e) {
LOG.error("--- foo message ---");
throw new SvcException("failed to connect", e); // wrap e inside SvcException
}
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new SvcException("message replied with error");
}
}
这里注意response是在try循环之前声明的。它没有被初始化,因为没有值它无法到达 !response.getBoolean(SUCCESS)
测试。如果 makeNetworkCall() 抛出异常,它甚至不会到达该行。
void connectOverNetwork() throws Exception {
try {
final JSONObject response = make network call;
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new Exception("message replied with error");
}
} catch (final Exception e) {
LOG.error("---- bar message ---");
throw new SvcException("failed to connect over network");
}
}
在上面的代码中,我抛出了一个带有失败消息的异常。 同时,我也报了网络连接失败的错误。
但是,如果我为 !success
抛出异常,它会再次被捕获,导致重复记录。如果我只想记录 foo message
.
bar message
如何预防?
验证 try-catch
语句后的 response
。
JSONObject response = null;
try {
response = /* make network call */;
} catch (final Exception e) {
LOG.error("---- bar message ---");
throw new SvcException("failed to connect over network");
}
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new Exception("message replied with error");
}
我不建议捕获 Exception
- 它太笼统了,我建议您将其缩小到更具体的异常类型。
如果将它移到 try
块之外怎么办。无论如何,第一个 try..catch
的原因是要捕获来自网络调用的任何异常。
JSONObject response = null;
try {
response = make network call;
} catch (final Exception e) {
LOG.error("---- bar message ---");
throw new SvcException("failed to connect over network");
}
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new Exception("message replied with error");
}
创建您自己的异常类型并且不捕获它。
try {
do stuff
if (condition)
throw new MyCustomException("error")
} catch (IOException e) {
log and rethrow
}
首先,让我指出您代码中的一个错误。您的方法声明它抛出异常,但它没有。它抛出 SvcException。所以这就是 "throws" 子句应该说的。 (无论如何你都不应该说 "throws Exception" 。你应该明确说明它抛出的异常类型。)其余的答案取决于你的模糊描述 "make network call" 是否抛出异常。
如果没有,您的方法应如下所示:
void connectOverNetwork() throws SvcException {
final JSONObject response = makeNetworkCall();
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new SvcException("message replied with error");
}
}
但这不现实。很有可能,您的 "make network call" 代码会抛出类似 IOException 的异常。在这种情况下,您的代码应如下所示:
void connectOverNetwork() throws SvcException {
try {
final JSONObject response = makeNetworkCall(); // throws IOException
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new SvcException("message replied with error");
}
} catch (final IOException e) {
LOG.error("--- foo message ---");
throw new SvcException("failed to connect", e); // wrap e inside SvcException
}
}
请注意,我将捕获的 IOException 包装在 SvcException 中。如果您的 SvcException 不这样做,要么重写它以便它可以,要么在抛出它之前调用它的 initCause()
方法。在重新抛出不同的异常时,您应该始终包含原始异常。
另请注意,我没有费心抛出,然后捕获并重新抛出 IOException。当我检测到故障时。我只是抛出我需要抛出的异常。这意味着我需要在两个不同的地方记录 foo 消息。对于大多数事情,应该避免重复一行代码,但是对于日志记录,这很好。
但是这段代码有点乱。我会通过将成功测试与可能的 IOException 分开来清理它。所以我会这样写:
void connectOverNetwork() throws SvcException {
JSONObject response; // no need to initialize this.
try {
response = makeNetworkCall(); // throws IOException
} catch (final IOException e) {
LOG.error("--- foo message ---");
throw new SvcException("failed to connect", e); // wrap e inside SvcException
}
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new SvcException("message replied with error");
}
}
这里注意response是在try循环之前声明的。它没有被初始化,因为没有值它无法到达 !response.getBoolean(SUCCESS)
测试。如果 makeNetworkCall() 抛出异常,它甚至不会到达该行。