在Java中,我们可以捕获某种类型的异常:
try{
// Code that does IO like download a file...
}catch(IOException ioe){
ioe.printStackTrace();
// handle ioe
}catch(SomeOtherException soe){
// handle soe
}
现在,可能有多种原因导致异常,在这种情况下,IOException
可以是:
java.io.IOException: Illegal character in path at index.....
来自特定的图书馆或其他类似的文章:
java.io.IOException: Stream closed ...
如果Stream
现在,我的问题是,如何确定IOException
发生了什么?
如何区分Stream closed
和Illegal character in path at index...
?
当然我可以查看异常消息的字符串,但我认为这不是最好的方法,因为底层库/实现可以更改消息字符串。
修改
在这种情况下, e.getClass()
几乎所有内容都会返回java.io.IOException
...
我猜图书馆在放弃任何原始IOException
的同时抛出了自己的Exception
。
答案 0 :(得分:7)
printStackTrace
打印的事实
java.io.IOException: Stream closed ...
// ^^^^^^^^^^^
和
java.io.IOException: Illegal character in path at index.....
// ^^^^^^^^^^^
表示Exception
的类型为IOException
。您可以在此处使用更具体的子类型。
在这种情况下没有办法。他们决定为这两个(以及更多)原因使用相同的Exception
类型。您将无法使用不同的catch
语句区分它们。你需要检查他们的信息。
如果Exception
有cause
,您必须查看是否有区别类型并重新抛出它。如果幸运的话,您可以捕获更具体的Exception
类型。
答案 1 :(得分:4)
您可以区别对待异常,因为IOException
是子异常的顶级层次结构
java.io.IOException
java.io.CharConversionException
java.io.EOFException
java.io.FileNotFoundException
java.io.InterruptedIOException
java.io.ObjectStreamException
java.io.InvalidClassException
java.io.InvalidObjectException
java.io.NotActiveException
java.io.NotSerializableException
java.io.OptionalDataException
java.io.StreamCorruptedException
java.io.WriteAbortedException
java.io.SyncFailedException
java.io.UnsupportedEncodingException
java.io.UTFDataFormatException
java.io.UnsupportedEncodingException
java.io.UTFDataFormatException
答案 2 :(得分:2)
当一个库引发一个过于通用的异常时(看起来,你似乎遇到了IOException
),你很遗憾没有很多好的选择 - 实际上这是一个糟糕的设计图书馆的一部分。理想情况下,您应该提交错误或提交违规库的拉取请求,但这可能是不可能或不可行的。
然而一切都没有丢失。首先,通过Throwable.getCause()
包含通用IOException
基础原因,图书馆实际上可能会提供比您想象的更多信息。这是一种提供更详细调试信息的强大方法,同时为正常处理公开单个Exception
。如果这个库遵循这种做法,你可以这样做:
catch(IOException e) {
Throwable cause = e.getCause();
if(cause != null && cause instanceof URISyntaxException) {
System.err.println("Bad URI");
} else {
System.err.println("Other IOException");
}
}
当然,将一些谷歌搜索建议的URISyntaxException
改为IOException
并不是一个非常好的设计(无效的URI肯定不是IO问题)所以我不会如果图书馆只是调用类似throw new IOException(e.getMessage())
的内容并丢弃原文,那就不足为奇了,这意味着你不得不继续下去就是例外的消息。
就像你注意到的那样,解析异常消息并不是一个非常好的主意。理想情况下,您应该将这种不良行为包装到辅助方法中,以便在改进库后可以轻松地重构它,并检测是否发生了任何意外情况并解决它。考虑:
public void doOperation(arguments) throws IOException, URISyntaxException {
try {
BadLibrary.doOperation(arguments);
} catch(IOException e) {
if(e.getMessage().startsWith("Illegal character")) {
throw new URISyntaxException("Uknown", e.getMessage());
} else if(e.getMessage().startsWith("Stream closed")) {
throw e;
} else {
// note we include the cause here
throw new RuntimeException("Unexpected exception from BadLibrary", e);
}
}
}
通过这种划分,你只需要在一个地方进行这种令人不快的检查,并且可以合理地确信你会发现对底层库的意外更改,而不是默默地忽略它们。