【问题标题】:Why it is okay in java 7 to catch an IOException even if IOException will never be thrown为什么即使永远不会抛出 IOException 也可以在 java 7 中捕获 IOException
【发布时间】:2014-12-21 02:34:20
【问题描述】:
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 块中抛出。

【问题讨论】:

  • 为什么不应该呢?你是老板。你决定做什么,即使它是愚蠢的。
  • IOException 扩展异常
  • 编译器不知道永远不会抛出 IOException。你也没有。

标签: java exception exception-handling try-with-resources


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    您的困惑可能是,在 Java 7 中,[声明为]从 close 方法抛出的异常被抛出 inside try 块,所以你的 catch 块有抓住它。

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

    由于IOExceptionException 的子类,当然你也可以尝试捕捉它,只要你自己也捕捉/声明Exception

    JLS 14.20.3.2:

    给出了扩展的 try-with-resources 语句 [...] 的含义 通过以下翻译为基本的 try-with-resources 语句 (§14.20.3.1) 嵌套在 try-catch 或 try-finally 或 try-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");
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-10
      • 1970-01-01
      • 2021-03-05
      • 2012-01-13
      • 2012-09-21
      • 1970-01-01
      • 2017-05-24
      • 1970-01-01
      相关资源
      最近更新 更多