【问题标题】:How to avoid throwing exception from finally block如何避免从finally块抛出异常
【发布时间】:2021-01-27 10:20:35
【问题描述】:

我不想让 toJson 抛出异常,但 finally 块可能会抛出它。 是否最好将bas.close() 包装在 try/catch 块中,或者是否应该使用 try-with-resources 重写它

public String toJson() {
    String json = null;
    ByteArrayOutputStream bas = null;

    try {
        bas = new ByteArrayOutputStream();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.writeValue(bas, this);

        json = new String(bas.toByteArray());
    } catch (Exception e) {
        log.trace("Unable to parse JSON", e); 
    } finally {
        if (bas != null) {
            bas.close();
        }   
    }   

    return json;
}   

【问题讨论】:

  • 是的,它应该被重写为try-with-resources,这对于所有可自动关闭的资源都是首选。
  • 简单,不要扔一个。但是,老实说,我看不到您当前的方法会抛出异常
  • @Stultuske ByteArrayOutputStream.close() 记录为“如果发生 I/O 错误”会引发异常。
  • 您不必关闭ByteArrayOutputStream stackoverflow.com/questions/2330569/…
  • @AndyTurner 但它也被记录为什么都不做:ByteArrayOutputStream.close():“关闭 ByteArrayOutputStream 无效。可以在关闭流后调用此类中的方法而不会生成 IOException。 "

标签: java exception


【解决方案1】:

您应该使用 try-with-resources 语句来执行此操作。下面是 Oracle 在 The try-with-resources Statement 上的教程的摘录,其中清楚地说明了使用它的好处:

在 Java SE 7 之前,您可以使用 finally 块来确保 无论try 语句是否完成,资源都会关闭 通常或突然。以下示例使用 finally 块 而不是 try-with-resources 语句:

static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

但是,在本例中,如果方法 readLineclose 都抛出 异常,然后方法readFirstLineFromFileWithFinallyBlock 抛出从finally 块抛出的异常;例外 从try 块抛出的内容被抑制。相反,在示例中 readFirstLineFromFile,如果两个 try 都抛出异常 块和 try-with-resources 语句,然后是方法 readFirstLineFromFile 抛出从 try 块抛出的异常; 从 try-with-resources 块抛出的异常被抑制。 在 Java SE 7 及更高版本中,您可以检索被抑制的异常;看 有关更多信息,请参阅抑制的异常部分。

使用 try-with-resources 语句,您可以编写如下方法:

public String toJson() throws Exception {
    String json = null;

    try (ByteArrayOutputStream bas = new ByteArrayOutputStream()) {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.writeValue(bas, this);

        json = new String(bas.toByteArray());
    } 
    return json;
}   

【讨论】:

    【解决方案2】:

    我可能会采取以下方式:

    public String toJson() {
    
        try (var bas = new ByteArrayOutputStream()) {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.writeValue(bas, this);
            return new String(bas.toByteArray());
        }       
        catch (Exception ie) {
            throw new MyCustomJsonConverterException("Failed to render to JSON");
        }
    }
    

    i.e. 映射到 RuntimeException type,如果您预计无法序列化为 JSON 是异常的(编程错误)。毕竟,这是一个实例方法,并且该类的所有不变量都应该已经在其他地方强制执行。这样,您就可以从调用者那里检查null

    【讨论】:

      猜你喜欢
      • 2010-10-03
      • 1970-01-01
      • 2013-03-09
      • 2012-08-22
      • 1970-01-01
      • 1970-01-01
      • 2012-09-20
      • 1970-01-01
      相关资源
      最近更新 更多