实例变量可以有效地最终化/在 Java 中只有局部变量有效地最终化吗?
Can instance variables be effectively final / Are only local variables effectively final in Java?
我想在 Java9 中使用 try-with-resources 增强功能,方法是将引用变量放入 try with resources 而不是整个变量声明中。我也知道要做到这一点,我必须遵循规则:Variable used as a try-with-resources resource should be final or effectively final
。首先,我将尝试使用本地变量,然后使用实例变量。
- 局部变量:
-我将变量设置为 final,它遵循给定的规则并可以正常编译:
public static void main (String[] args) throws IOException{
final FileWriter fw = new FileWriter ("test.txt");
try(fw) {
//some code
}
}
-如果我也删除了 final 关键字,它将再次编译,因为 fw
被认为是 effectively final -变量只初始化一次,从不改变。
public static void main (String[] args) throws IOException{
FileWriter fw = new FileWriter ("test.txt");
try(fw) {
//some code
}
}
- 实例变量:
但是同样的模式也适用于实例变量吗?试试吧。
-首先让实例变量final,它再次遵循规则并编译得很好:
public class Test {
final FileWriter fw = new FileWriter ("a.txt");
void m1() throws IOException {
try(fw ) {
//some code
}
}
}
-如果我删除 final 关键字,它应该再次编译,应该吗?因为我没有在任何地方改变 fw
而是只初始化一次 - 应该是 最终有效 。不幸的是,这行不通:
public class Test {
FileWriter fileWriter = new FileWriter ("a.txt");
void m1() throws IOException {
try(fileWriter) {
//some code
}
}
}
它给我消息:用作 try-with-resources 资源的变量应该是最终的或有效的最终。所以在这一切之后,我回到我的第一个问题。实例变量可以 有效地最终 还是该术语仅用于局部变量?正如我刚刚展示的那样,我从不改变变量(应该被视为 有效最终),但编译器从不威胁它。
Java Language Specification, section 4.12.4. final
Variables,明确规定只有局部变量和参数才能有效final:
Certain variables that are not declared final
are instead considered effectively final:
A local variable whose declarator has an initializer (§14.4.2) is effectively final if all of the following are true:
It is not declared final
.
It never occurs as the left hand side in an assignment expression (§15.26). (Note that the local variable declarator containing the initializer is not an assignment expression.)
It never occurs as the operand of a prefix or postfix increment or decrement operator (§15.14, §15.15).
A local variable whose declarator lacks an initializer is effectively final if all of the following are true:
It is not declared final
.
Whenever it occurs as the left hand side in an assignment expression, it is definitely unassigned and not definitely assigned before the assignment; that is, it is definitely unassigned and not definitely assigned after the right hand side of the assignment expression (§16 (Definite Assignment)).
It never occurs as the operand of a prefix or postfix increment or decrement operator.
A method, constructor, lambda, or exception parameter (§8.4.1, §8.8.1, §9.4, §15.27.1, §14.20) is treated, for the purpose of determining whether it is effectively final, as a local variable whose declarator has an initializer.
If a variable is effectively final, adding the final
modifier to its declaration will not introduce any compile-time errors. Conversely, a local variable or parameter that is declared final
in a valid program becomes effectively final if the final
modifier is removed.
我想在 Java9 中使用 try-with-resources 增强功能,方法是将引用变量放入 try with resources 而不是整个变量声明中。我也知道要做到这一点,我必须遵循规则:Variable used as a try-with-resources resource should be final or effectively final
。首先,我将尝试使用本地变量,然后使用实例变量。
- 局部变量:
-我将变量设置为 final,它遵循给定的规则并可以正常编译:
public static void main (String[] args) throws IOException{
final FileWriter fw = new FileWriter ("test.txt");
try(fw) {
//some code
}
}
-如果我也删除了 final 关键字,它将再次编译,因为 fw
被认为是 effectively final -变量只初始化一次,从不改变。
public static void main (String[] args) throws IOException{
FileWriter fw = new FileWriter ("test.txt");
try(fw) {
//some code
}
}
- 实例变量:
但是同样的模式也适用于实例变量吗?试试吧。
-首先让实例变量final,它再次遵循规则并编译得很好:
public class Test {
final FileWriter fw = new FileWriter ("a.txt");
void m1() throws IOException {
try(fw ) {
//some code
}
}
}
-如果我删除 final 关键字,它应该再次编译,应该吗?因为我没有在任何地方改变 fw
而是只初始化一次 - 应该是 最终有效 。不幸的是,这行不通:
public class Test {
FileWriter fileWriter = new FileWriter ("a.txt");
void m1() throws IOException {
try(fileWriter) {
//some code
}
}
}
它给我消息:用作 try-with-resources 资源的变量应该是最终的或有效的最终。所以在这一切之后,我回到我的第一个问题。实例变量可以 有效地最终 还是该术语仅用于局部变量?正如我刚刚展示的那样,我从不改变变量(应该被视为 有效最终),但编译器从不威胁它。
Java Language Specification, section 4.12.4. final
Variables,明确规定只有局部变量和参数才能有效final:
Certain variables that are not declared
final
are instead considered effectively final:
A local variable whose declarator has an initializer (§14.4.2) is effectively final if all of the following are true:
It is not declared
final
.It never occurs as the left hand side in an assignment expression (§15.26). (Note that the local variable declarator containing the initializer is not an assignment expression.)
It never occurs as the operand of a prefix or postfix increment or decrement operator (§15.14, §15.15).
A local variable whose declarator lacks an initializer is effectively final if all of the following are true:
It is not declared
final
.Whenever it occurs as the left hand side in an assignment expression, it is definitely unassigned and not definitely assigned before the assignment; that is, it is definitely unassigned and not definitely assigned after the right hand side of the assignment expression (§16 (Definite Assignment)).
It never occurs as the operand of a prefix or postfix increment or decrement operator.
A method, constructor, lambda, or exception parameter (§8.4.1, §8.8.1, §9.4, §15.27.1, §14.20) is treated, for the purpose of determining whether it is effectively final, as a local variable whose declarator has an initializer.
If a variable is effectively final, adding the
final
modifier to its declaration will not introduce any compile-time errors. Conversely, a local variable or parameter that is declaredfinal
in a valid program becomes effectively final if thefinal
modifier is removed.