Java精确地识别异常

Java精确地识别异常,java,exception,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.IOExc

在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 ...
如果
流出现问题

现在,我的问题是,如何确定发生了什么类型的
IOException

如何区分索引处路径中的
流关闭的
非法字符…

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

编辑:

e.getClass()
在本例中,几乎所有内容都返回
java.io.IOException


我猜库会抛出自己的
IOException
,同时丢弃任何原始的
异常

事实是
printStackTrace
已打印

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

表示
异常
类型为
IOException
。这里没有更具体的子类型可以使用

在这种情况下没有办法。出于上述两个(或更多)原因,他们决定使用相同的
异常
类型。您将无法使用不同的
catch
语句来区分它们。你需要检查他们的留言


如果
异常
有一个
原因
,则必须查看是否有可区分的类型,然后重新显示它。如果幸运的话,您可能能够捕获更具体类型的
异常

您可以以不同的方式捕获异常,因为
IOException
是子异常的顶级层次结构

发件人:


当一个库引发一个太一般的异常时(看起来,你在这里遇到了
IOException
),不幸的是,你没有很多好的选择——从本质上说,这是库的糟糕设计。理想情况下,您应该为有问题的库提交bug或pull请求,但这可能是不可能或不可行的

然而,一切都没有失去。首先也是最重要的一点是,通过在generic
IOException
中包含潜在原因via,库可能实际上提供了比您想象的更多的信息。这是一种提供更详细调试信息的健壮方法,同时为正常处理公开单个
异常。如果此库遵循此做法,您可以执行以下操作:

catch(IOException e) {
  Throwable cause = e.getCause();
  if(cause != null && cause instanceof URISyntaxException) {
    System.err.println("Bad URI");
  } else {
    System.err.println("Other IOException");
  }
}
当然,将Google建议的
URISyntaxException
转换为
IOException
一开始并不是一个非常好的设计(无效的URI肯定不是IO问题),所以如果库只是调用
throw new IOException(e.getMessage())之类的东西,我也不会感到惊讶
并丢弃原始版本,不幸的是,您只需继续处理异常消息

正如您所注意到的,解析异常消息并不是一个非常好的主意。理想情况下,您应该将这种糟糕的行为包装到一个helper方法中,以便在库得到改进后可以轻松地将其重构出来,并检测是否发生意外情况并解决它。考虑:

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

通过这种划分,您只需在一个地方执行这种令人不快的检查,并且有理由相信您将检测到对底层库的意外更改,而不是默默地忽略它们。

在OP的情况下,异常的具体类型似乎是
IOException
。更具体的子类型没有帮助。是的,我做了一个编辑,请检查更新的问题。我投票给你,因为这是唯一看到
IOEeception
并知道它是一个具体类型的答案。我不知道为什么会有人首先否决你…@HovercraftFullOfEels
printStackTrace
方法取决于
toString
方法。
Throwable
实现使用
getClass().getName()
打印类名。因此,除非
StreamClosedException
重写其
toString
以返回
IOException
类名,否则具体类型为
IOException
@HovercraftFullOfEels无需:)原因是空的,所以我想唯一的方法是对
非法字符执行
String.contains()
现在…@tom暂时,你可以这样做。但是,该消息是特定于实现的。如果它改变了,你也必须这样做。你打算做什么不同的处理?
catch(IOException e) {
  Throwable cause = e.getCause();
  if(cause != null && cause instanceof URISyntaxException) {
    System.err.println("Bad URI");
  } else {
    System.err.println("Other IOException");
  }
}
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);
    }
  }
}