为什么try-with-resources catch块选择性地可选?

我读到try-with-resources中的catch块是可选的。 我尝试在try-with-resources块中创建一个Connection对象,没有后续的catch块,只是为了从eclipse中获取编译器错误:“自动close()调用引发的未处理的exception类型SQLException 。”

由于可以在try-with-resources中使用的每个资源都实现了AutoCloseable ,因此在调用close()方法时可能抛出exception,我不明白catch子句是如何可选的,因为它不允许我跳过从close()捕获exception。

是否有一些特殊要求, AutoCloseable的具体实现不直接声明其close()方法中抛出的任何exception? (例如,重写AutoCloseableclose() throws Exception一个带有close()exception,它不会抛出任何exception)?

..或者这可能只是一个日食问题?

编辑:这是仍然触发问题的最简单的代码片段:

 try (Connection con = dataSource.getConnection()) { /*...*/ } 

关于这是否与使用JNDI数据源有关的想法?

提前致谢。

如果close()无法抛出已检查的exception,则它是可选的。 但是,如果close()可以,则需要以正常方式处理已检查的exception,或者使用catch块,或者通过从try-with-resources块所在的方法中抛出。

更多细节见JLS 14.2.3

14.20.3.2。 扩展资源尝试

具有至少一个catch子句和/或finally子句的try-with-resources语句称为扩展的try-with-resources语句。

扩展的try-with-resources语句的含义:

 try ResourceSpecification Block [Catches] [Finally] 

通过以下转换给出嵌套在try-catch或try-finally或try-catch-finally语句中的基本try-with-resources语句:

 try { try ResourceSpecification Block } [Catches] [Finally] 

翻译的效果是将资源规范放在try语句的“内部”。 这允许扩展的try-with-resources语句的catch子句捕获由于自动初始化或关闭任何资源而导致的exception。

此外,所有资源将在执行finally块时关闭(或尝试关闭),以符合finally关键字的意图。

关于这是否与使用JNDI数据源有关的想法?

是的。

在您提供的try-with-resourses块示例中,必须捕获exception并处理,或者从块所在的方法中抛出,因为SQLException是一个经过检查的exception。

你可以抛出exception(或者在另一个try-catch块中捕获它):

 private static void test() throws IOException { try(InputStream is = new FileInputStream("test.txt")) { while(is.read() > -1) { } } finally { // Will get executed, even if exception occurs System.out.println("Finished"); } } 

并非每个Java类(!)都会抛出exception。 有时您只想使用try-with-resources来使用自动关闭function,而不是别的。

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

这个catch是可选的,因为readLine()不会抛出(已检查)exception。

是的,close()可能会抛出exception,但try-with-resources也会处理exception。

 try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } 

因此,这种资源尝试不需要捕获。

您可以检查JLS,但实际上有一个相对简单的推理,为什么这是语言应该表现的唯一正确方法。

已检查exception的主要规则是必须处理由方法声明的任何已检查exception,方法是捕获它或让调用方法抛出它。

try-with-resources总是(隐式地)调用close方法。

因此,如果您使用的AutoClosable的特定close方法(由try中声明的类型确定)声明抛出一个已检查的exception,例如SQLException,则需要在某处处理此已检查的exception,否则可能违反该规则!

如果close方法声明它抛出已检查的exception,则不会违反该规则,并且您不需要处理已检查的exception以隐式调用close方法。 如果您尝试捕获从未声明为抛出的已检查exception,则实际上是编译失败。