我读到try-with-resources中的catch
块是可选的。
我尝试在try-with-resources块中创建一个Connection
对象,没有后续的catch
块,只是为了从eclipse中获取编译器错误:
“自动SQLException
调用引发的未处理异常类型close()
。”
由于可以在try-with-resources中使用的每个资源都实现AutoCloseable
,因此在调用close()
方法时可能会抛出异常,我不明白{{1因为它不允许我跳过从catch
捕获异常,所以子句是可选的。
是否有一些特殊要求close()
的具体实现不直接声明其AutoCloseable
方法中抛出的任何异常? (例如,使用close()
覆盖AutoCloseable
的{{1}},但不会抛出任何异常)?
..或者这可能只是一个日食问题?
编辑:这是仍然触发问题的最简单的代码片段:
close() throws Exception
关于这是否与使用JNDI数据源有关的想法?
提前致谢。
答案 0 :(得分:21)
如果close()
无法抛出已检查的异常,则可选。但是,如果close()
可以,则需要以正常方式处理已检查的异常,或者使用catch
块,或者通过抛出try-with-resources
块所在的方法来处理。 / p>
更多详情请见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子句捕获由于自动初始化或关闭任何资源而导致的异常。
此外,在执行finally块时,所有资源都将被关闭(或尝试关闭),与finally关键字的意图保持一致。
关于这是否与使用JNDI数据源有关的想法?
是的,确实如此。
在您提供的示例 try-with-resourses 块中,有必要捕获异常并处理,或者从块所在的方法中抛出,因为SQLException
是一个经过检查的例外
答案 1 :(得分:2)
你可能只是抛出异常(或在另一个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");
}
}
答案 2 :(得分:0)
并非每个Java类(!)都会抛出异常。有时你只想使用try-with-resources来使用自动关闭功能,而不是别的。
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
这个catch是可选的,因为readLine()不会抛出(已检查)异常。
是的,close()可能会抛出异常,但try-with-resources也会处理异常。
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
因此,这种资源尝试并不需要捕获。
答案 3 :(得分:0)
您可以检查JLS,但实际上有一个相对容易的理由,为什么这是语言应该表现的唯一正确方法。
已检查异常的主要规则是必须处理方法声明的任何已检查异常,方法是捕获它或让调用方法抛出它。
try-with-resources总是(隐式地)调用close方法。
因此,如果您使用的AutoClosable的特定close方法(由 try 中声明的类型确定)声明抛出已检查的异常(例如SQLException),则需要在某处处理此已检查的异常,否则就有可能违反规则!
如果close方法不声明它抛出一个已检查的异常,则不会违反该规则,并且您不需要处理已检查的异常以隐式调用close方法。如果您尝试捕获从未声明为抛出的已检查异常,则实际上是编译失败。
答案 4 :(得分:0)
通过声明无任何异常或带有RuntimeException的AutoClosable的close()方法,可以创建不需要显式捕获块的AutoClosable。没有任何例外,很明显,不需要catch块。此外,编译器不会静态检查要捕获的RuntimeException(与检查的Exception相反)。
示例:
public class AutoClosableDemo
{
public static void main( final String[] args )
{
try (MyAutoCloseable1 mac1 = new MyAutoCloseable1())
{
System.out.println( "try-with-resource MyAutoCloseable1" );
}
try (MyAutoCloseable2 mac2 = new MyAutoCloseable2())
{
System.out.println( "try-with-resource MyAutoCloseable2" );
}
// The following is not allowed, because
// "Unhandled exception type Exception thrown by automatic close() invocation on mac3"
// try (MyAutoCloseable3 mac3 = new MyAutoCloseable3())
// {
// System.out.println( "try-with-resource MyAutoCloseable13" );
// }
System.out.println( "done" );
}
public static class MyAutoCloseable1 implements AutoCloseable
{
@Override
public void close()
{
System.out.println( "MyAutoCloseable1.close()" );
}
}
public static class MyAutoCloseable2 implements AutoCloseable
{
@Override
public void close() throws RuntimeException
{
System.out.println( "MyAutoCloseable2.close()" );
}
}
public static class MyAutoCloseable3 implements AutoCloseable
{
@Override
public void close() throws Exception
{
System.out.println( "MyAutoCloseable3.close()" );
}
}
}