4
public class SampleCloseable implements AutoCloseable {

    private String name;

    public SampleCloseable(String name){
        this.name = name;
    }

    @Override
    public void close() throws Exception {
        System.out.println("closing: " + this.name);
    }
}

和主要课程

public class Main{

    public static void main(String args[]) {
      try(SampleCloseable sampleCloseable = new SampleCloseable("test1")){

          System.out.println("im in a try block");

      } catch (IOException  e) {
          System.out.println("IOException is never thrown");

      } catch (Exception e) {

      } finally{
          System.out.println("finally");
      }

    }
}

但是,当我在 SampleCloseable 内的 close() 方法上删除 throws 异常时,我收到一个编译器错误,指出 IOException 永远不会在相应的 try 块中引发。

4

2 回答 2

10

因为你抛出了一个通用的异常。由于 IOException 继承自 Exception,因此它可能被 close() 方法抛出。调用者不知道它实际上并没有被抛出。它只看到表明它可以的方法签名。

事实上,close() 方法可以随意抛出任何类型的异常。当然这是不好的做法,您应该指定要抛出的特定异常。

于 2014-12-21T02:42:35.640 回答
1

您可能会感到困惑的是,在 Java 7 中,[声明为]从close方法中抛出的异常是在 try 块抛出的,因此您的 catch 块也必须捕获它。

您的close方法被声明为抛出异常,因此您的catch块必须捕获它,或者必须将方法声明为 throw Exception

既然IOException是 的子类Exception,你当然也可以尝试捕捉它,只要你也捕捉/声明Exception自己。

JLS 14.20.3.2

扩展的 try-with-resources 语句 [...] 的含义由以下对嵌套在 try-catch 或 try-finally 或 try- 中的基本 try-with-resources 语句(第 14.20.3.1 节)的翻译给出catch-finally 语句。

您的代码被有效地翻译为以下内容。虽然有点冗长,但从下面的代码中应该可以清楚地看到代码中发生了什么。

public static void main(String args[]) {
  try {
      Throwable primaryEx = null ;
      SampleCloseable sampleCloseable = new SampleCloseable("test1")
      try {
          System.out.println("im in a try block");
      } catch (Throwable t) {
          primaryEx = t;
          throw t;
      } finally {
        if (sampleCloseable != null) {
        if (primaryEx != null) {
            try {
                sampleCloseable.close();
            } catch (Throwable suppressedExc) {
                primaryEx.addSuppressed(suppressedExc);
            }
        } else {
            sampleCloseable.close();
        }
      }
  } catch (IOException  e) {
      System.out.println("IOException is never thrown");

  } catch (Exception e) {

  } finally{
      System.out.println("finally");
  }
}
于 2014-12-21T05:04:06.440 回答