java 为什么 try-with-resources catch 块是选择性可选的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25497053/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is try-with-resources catch block selectively optional?
提问by Mer
I read that the catch
block in try-with-resources is optional.
I've tried creating a Connection
object in a try-with-resources block, with no subsequent catch
block, only to get compiler error from eclipse:
"Unhandled exception type SQLException
thrown by automatic close()
invocation."
我读到catch
try-with-resources中的块是可选的。我尝试Connection
在 try-with-resources 块中创建一个对象,没有后续catch
块,只是为了从 eclipse 中获取编译器错误:“SQLException
自动close()
调用抛出的未处理的异常类型。”
Since every resource that can be used in try-with-resources implements AutoCloseable
, and so potentially throws an exception upon invocation of the close()
method, I don't understand how the catch
clause is optional, given that it's not allowing me to skip catching the exception from close()
.
由于可以在 try-with-resources 中使用的每个资源都实现了AutoCloseable
,因此在调用该close()
方法时可能会抛出异常,我不明白该catch
子句是如何可选的,因为它不允许我跳过从close()
.
Is there some special requirement that the specific implementation of AutoCloseable
not directly declare any exception thrown in its close()
method? (e.g. override AutoCloseable
's close() throws Exception
with a close()
which does not throw any Exception)?
有没有什么特殊的要求,具体实现AutoCloseable
不直接声明其close()
方法抛出的异常?(如覆盖AutoCloseable
的close() throws Exception
一个close()
不抛出任何异常)?
..or is this possibly just an eclipse issue?
..或者这可能只是日食问题?
Edit: Here's the simplest code fragment that still triggers the problem:
编辑:这是仍然触发问题的最简单的代码片段:
try (Connection con = dataSource.getConnection()) {
/*...*/
}
Thoughts on whether or not this is related to the use of a JNDI DataSource?
关于这是否与使用 JNDI 数据源有关的想法?
Thanks in advance.
提前致谢。
采纳答案by jdphenix
It is optional if close()
is not able to throw a checked exception. However, if close()
can, then a checked exception would need to handled in a normal fashion, either with a catch
block, or by throwing from the method that try-with-resources
block is in.
如果close()
无法抛出已检查的异常,则它是可选的。但是,如果close()
可以,那么检查异常将需要以正常方式处理,要么使用catch
块,要么从该try-with-resources
块所在的方法中抛出。
More details are in JLS 14.2.3
更多细节在JLS 14.2.3
14.20.3.2. Extended try-with-resources
A try-with-resources statement with at least one catch clause and/or a finally clause is called an extended try-with-resources statement.
The meaning of an extended try-with-resources statement:
14.20.3.2. 扩展的尝试资源
带有至少一个 catch 子句和/或 finally 子句的 try-with-resources 语句称为扩展的 try-with-resources 语句。
扩展的 try-with-resources 语句的含义:
try ResourceSpecification
Block
[Catches]
[Finally]
is given by the following translation to a basic try-with-resources statement nested inside a try-catch or try-finally or try-catch-finally statement:
由以下转换为嵌套在 try-catch 或 try-finally 或 try-catch-finally 语句中的基本 try-with-resources 语句给出:
try {
try ResourceSpecification
Block
}
[Catches]
[Finally]
The effect of the translation is to put the resource specification "inside" the try statement. This allows a catch clause of an extended try-with-resources statement to catch an exception due to the automatic initialization or closing of any resource.
Furthermore, all resources will have been closed (or attempted to be closed) by the time the finally block is executed, in keeping with the intent of the finally keyword.
翻译的效果是将资源规范“放在”try 语句中。这允许扩展的 try-with-resources 语句的 catch 子句捕获由于任何资源的自动初始化或关闭而引起的异常。
此外,在执行 finally 块时,所有资源都将关闭(或试图关闭),这与 finally 关键字的意图保持一致。
Thoughts on whether or not this is related to the use of a JNDI DataSource?
关于这是否与使用 JNDI 数据源有关的想法?
Yes, it is.
是的。
In the example try-with-resoursesblock you've provided, it is necessary to catch the exception and handle, or throw from the method the block is in, because SQLException
is a checked exception.
在您提供的示例try-with-resources块中,有必要捕获异常并处理,或者从块所在的方法中抛出,因为SQLException
是已检查的异常。
回答by Robby Cornelissen
You could just be throwing the exception up (or catching it in another try-catch block):
您可能只是抛出异常(或在另一个 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");
}
}
回答by Henno Vermeulen
You could check the JLS but there is actually a relatively easy reasoning why this is the only correct way the language should behave.
您可以检查 JLS,但实际上有一个相对简单的推理,为什么这是语言应该表现的唯一正确方式。
The main rule of checked exceptions is that any checked exception declared by a method must be handled, either by catching it or letting the calling method throw it.
受检异常的主要规则是必须处理方法声明的任何受检异常,通过捕获它或让调用方法抛出它。
The try-with-resources always (implicitly) calls the close method.
try-with-resources 总是(隐式)调用 close 方法。
So if the specific close method of the AutoClosable you use (determined by the type declared in try) declares to throw a checked exception such as a SQLException you do need to handle this checked exception somewhere, otherwise it would be possible to violate the rule!
因此,如果您使用的 AutoClosable 的特定 close 方法(由try 中声明的类型决定)声明抛出检查异常,例如 SQLException 您确实需要在某处处理此检查异常,否则可能会违反规则!
If the close method does notdeclare that it throws a checked exception, the rule is not violated and you do not need to handle a checked exception for implicitly calling the close method. It is actually a compilation failure if you do try to catch a checked exception that is never declared to be thrown.
如果 close 方法没有声明它抛出已检查的异常,则不违反规则,您不需要处理已检查的异常来隐式调用 close 方法。如果您确实尝试捕获从未声明为抛出的已检查异常,则实际上是编译失败。
回答by mihca
You can create an AutoClosable that does not require an explicit catch-block by declaring your AutoClosable's close() method without any Exception or with a RuntimeException. Without any Exception it is clear that no catch-block is required. Further, the compiler does not statically check for a RuntimeException to be catched (in contrast to checked Exceptions).
您可以通过声明 AutoClosable 的 close() 方法而没有任何异常或使用 RuntimeException 来创建不需要显式捕获块的 AutoClosable。没有任何异常,很明显不需要 catch-block。此外,编译器不会静态检查要捕获的 RuntimeException(与检查的异常相反)。
Example:
例子:
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()" );
}
}
}
回答by markspace
Not every Java class (!) throws an exception. Sometimes you just want to use a try-with-resources to use the auto-close feature, and nothing else.
并非每个 Java 类 (!) 都会抛出异常。有时您只想使用 try-with-resources 来使用自动关闭功能,而不是别的。
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
This the catch is optional because readLine() doesn't throw a (checked) exception.
这个 catch 是可选的,因为 readLine() 不会抛出(检查)异常。
Yes, close() could throw an exception, but the try-with-resources handles that too.
是的,close() 可能会抛出异常,但 try-with-resources 也可以处理。
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
So this try-with-resources doesn't need a catch.
所以这个 try-with-resources 不需要捕获。