Java精确地识别异常

时间:2014-08-27 19:19:34

标签: java exception

在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 closedIllegal character in path at index...

当然我可以查看异常消息的字符串,但我认为这不是最好的方法,因为底层库/实现可以更改消息字符串。

修改

在这种情况下,

e.getClass()几乎所有内容都会返回java.io.IOException ...

我猜图书馆在放弃任何原始IOException的同时抛出了自己的Exception

3 个答案:

答案 0 :(得分:7)

printStackTrace打印的事实

java.io.IOException: Stream closed ...
//      ^^^^^^^^^^^

java.io.IOException: Illegal character in path at index.....
//      ^^^^^^^^^^^

表示Exception的类型为IOException。您可以在此处使用更具体的子类型。

在这种情况下没有办法。他们决定为这两个(以及更多)原因使用相同的Exception类型。您将无法使用不同的catch语句区分它们。你需要检查他们的信息。

如果Exceptioncause,您必须查看是否有区别类型并重新抛出它。如果幸运的话,您可以捕获更具体的Exception类型。

答案 1 :(得分:4)

您可以区别对待异常,因为IOException是子异常的顶级层次结构

来自documentation

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);
    }
  }
}

通过这种划分,你只需要在一个地方进行这种令人不快的检查,并且可以合理地确信你会发现对底层库的意外更改,而不是默默地忽略它们。