了解 Java 9 中的 try-with-resources 增强
Understanding try-with-resources enhancement in Java 9
不要在 中初始化 资源 ,而是尝试像这样使用资源块 :
try(FileWriter fw = new FileWriter ("java.txt")) {
//some operation
}catch (IOException ioe) {
ioe.printStackTrace ();
}
,我们现在可以只传递对 try with resources 块 的引用,我们希望自动关闭,如下所示:
FileWriter fw = new FileWriter ("java.txt");
try(fw) {
//some operation
}catch (IOException ioe){
ioe.printStackTrace ();
}
到目前为止,这部分已经很清楚了。我的问题是为什么我将在下一个示例中显示的代码不起作用?它与前面的示例有什么不同,后者编译得很好?
public class Test {
private FileWriter fileWriter;
public Test (FileWriter fileWriter) throws IOException {
this.fileWriter = fileWriter;
}
{
try(fileWriter) { //compile error:
//"Variable used as a try-with-resources resource should be final or effectively final""
}catch (IOException ioe){
ioe.printStackTrace ();
}
}
}
有人能帮我理解这条消息的意思吗?我不知道这里可能是什么问题。我也尝试把 final 放在 fileWriter
变量声明中,这并没有解决问题。
本质上是说Java要你保证你传递给try-with-resources(这里是fileWriter
)的变量一旦赋值就不会改变。如果可以更改变量(比如在 try 块本身内),则可能会出现各种未定义的行为。
从代码的角度来看,要使其正常工作,请在 fileWriter
的声明中添加 final
:
public class Test {
private final FileWriter fileWriter; // add 'final'
public Test (FileWriter fileWriter) throws IOException {
this.fileWriter = fileWriter;
}
// ... in some other method
private void foo() {
try(fileWriter) {
} catch (IOException ioe){
ioe.printStackTrace ();
}
}
}
我收到以下编译器错误,与您的不匹配:
The blank final field fileWriter may not have been initialized
这是因为您在 实例初始化程序 中引用 fileWriter
,它在超类构造函数调用和显式构造函数调用之后但在任何剩余代码之前执行构造函数。根据 JLS, Section 12.5, "Creation of New Class Instances":
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then
evaluate the arguments and process that constructor invocation
recursively using these same five steps. If that constructor
invocation completes abruptly, then this procedure completes abruptly
for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If
this constructor is for a class other than Object, then this
constructor will begin with an explicit or implicit invocation of a
superclass constructor (using super). Evaluate the arguments and
process that superclass constructor invocation recursively using these
same five steps. If that constructor invocation completes abruptly,
then this procedure completes abruptly for the same reason. Otherwise,
continue with step 4.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable
initializers to the corresponding instance variables, in the
left-to-right order in which they appear textually in the source code
for the class. If execution of any of these initializers results in an
exception, then no further initializers are processed and this
procedure completes abruptly with that same exception. Otherwise,
continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the
same reason. Otherwise, this procedure completes normally.
(粗体 强调我的)
这意味着您的构造函数尚未向 fileWriter
分配任何内容,从而导致实际错误。
在 fileWriter
的初始化之后将 try-with-resources 块放在构造函数中,或者将其移动到方法中。
不要在 中初始化 资源 ,而是尝试像这样使用资源块 :
try(FileWriter fw = new FileWriter ("java.txt")) {
//some operation
}catch (IOException ioe) {
ioe.printStackTrace ();
}
,我们现在可以只传递对 try with resources 块 的引用,我们希望自动关闭,如下所示:
FileWriter fw = new FileWriter ("java.txt");
try(fw) {
//some operation
}catch (IOException ioe){
ioe.printStackTrace ();
}
到目前为止,这部分已经很清楚了。我的问题是为什么我将在下一个示例中显示的代码不起作用?它与前面的示例有什么不同,后者编译得很好?
public class Test {
private FileWriter fileWriter;
public Test (FileWriter fileWriter) throws IOException {
this.fileWriter = fileWriter;
}
{
try(fileWriter) { //compile error:
//"Variable used as a try-with-resources resource should be final or effectively final""
}catch (IOException ioe){
ioe.printStackTrace ();
}
}
}
有人能帮我理解这条消息的意思吗?我不知道这里可能是什么问题。我也尝试把 final 放在 fileWriter
变量声明中,这并没有解决问题。
本质上是说Java要你保证你传递给try-with-resources(这里是fileWriter
)的变量一旦赋值就不会改变。如果可以更改变量(比如在 try 块本身内),则可能会出现各种未定义的行为。
从代码的角度来看,要使其正常工作,请在 fileWriter
的声明中添加 final
:
public class Test {
private final FileWriter fileWriter; // add 'final'
public Test (FileWriter fileWriter) throws IOException {
this.fileWriter = fileWriter;
}
// ... in some other method
private void foo() {
try(fileWriter) {
} catch (IOException ioe){
ioe.printStackTrace ();
}
}
}
我收到以下编译器错误,与您的不匹配:
The blank final field fileWriter may not have been initialized
这是因为您在 实例初始化程序 中引用 fileWriter
,它在超类构造函数调用和显式构造函数调用之后但在任何剩余代码之前执行构造函数。根据 JLS, Section 12.5, "Creation of New Class Instances":
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.
(粗体 强调我的)
这意味着您的构造函数尚未向 fileWriter
分配任何内容,从而导致实际错误。
在 fileWriter
的初始化之后将 try-with-resources 块放在构造函数中,或者将其移动到方法中。