为什么在Java 7中即使永远不会抛出IOException也可以捕获它?

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()方法中删除抛出异常的代码后,编译时会出现错误,提示在try块中未能抛出IOException异常。


为什么不可以呢?你是老板。即使是愚蠢的决定,也是由你做出的。 - Mathias Lykkegaard Lorenzen
3
IOException 是 Exception 的子类。 - gknicker
3
编译器不知道IOException永远不会被抛出。你也不知道。 - user207421
2个回答

10

因为你抛出了一个通用的 Exception。既然 IOException 继承自 Exception,close() 方法可能会抛出它。调用者不知道它实际上没有被抛出。它只看到方法签名说它可以。

事实上,close() 方法可以随意抛出任何类型的 Exception。当然这是不好的实践,你应该指定具体抛出哪些异常。


1
你可能感到困惑的是,在Java 7中,从close方法抛出的异常在try块内部被抛出,因此你的catch块也必须捕获它。
你的close方法被声明为抛出一个Exception,所以你的catch块必须捕获它,或者该方法必须被声明为抛出Exception
由于IOExceptionException的子类,当然你可以尝试并捕获它,只要你也捕获/声明Exception本身。
请参见JLS 14.20.3.2

扩展的try-with-resources语句的含义[...]由以下转换成嵌套在try-catch或try-finally或try-catch-finally语句内的基本try-with-resources语句(§14.20.3.1)给出。

你的代码已经被翻译成以下内容。虽然有点冗长,但从以下内容中应该清楚地了解你的代码正在发生什么。
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");
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接