为什么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? (例如,重写AutoCloseable
的close() 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,则实际上是编译失败。