为啥即使永远不会抛出 IOException 也可以在 java 7 中捕获 IOException
Posted
技术标签:
【中文标题】为啥即使永远不会抛出 IOException 也可以在 java 7 中捕获 IOException【英文标题】: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。你也没有。 【参考方案1】:因为你抛出了一个通用的异常。由于 IOException 继承自 Exception,因此它可能被 close() 方法抛出。调用者不知道它实际上并没有被抛出。它只看到表明它可以的方法签名。
事实上,close() 方法可以随意抛出任何类型的异常。当然这是不好的做法,您应该指定要抛出的特定异常。
【讨论】:
【参考方案2】:您的困惑可能是,在 Java 7 中,[声明为]从 close
方法抛出的异常被抛出 inside try 块,所以你的 catch 块有抓住它。
您的close
方法被声明为抛出一个异常,因此您的catch
块必须捕获它,或者该方法必须被声明为抛出Exception
。
由于IOException
是Exception
的子类,当然你也可以尝试捕捉它,只要你自己也捕捉/声明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");
【讨论】:
以上是关于为啥即使永远不会抛出 IOException 也可以在 java 7 中捕获 IOException的主要内容,如果未能解决你的问题,请参考以下文章
为啥即使我 .catch() Promise.all() 也会抛出异常?