这在java中是否允许:
for(int i=0;i<5;i++){
final int myFinalVariable = i;
}
我的问题的关键字是final
。是否允许做一个随着循环的每次运行而改变的最终变量?我想知道这一点,因为 final 说您不能更改变量的值(仅调用myFinalVariable = i
),但我正在重新定义整个变量final int
。
它们是两个完全不同的变量,只是同名吗?循环上一次运行的变量已经在通往垃圾收集器的路上了?
是的,这是允许的。final
关键字意味着您不能在其范围内更改变量的值。对于您的循环示例,您可以认为变量在循环底部超出范围,然后在循环顶部以新值返回范围。分配给循环内的变量将不起作用。
您是对的,对于循环中的每次迭代,您都在创建一个新变量。这些变量确实共享相同的名称,但这很好,因为它们不在同一个范围内。下一个示例不起作用:
final int myFinalVariable = 0;
for(int i=0;i<5;i++){
myFinalVariable = i;
}
变量只是堆栈上的一个位置。尝试将变量保持在尽可能小的范围内,并尝试使它们成为最终变量。然而,范围和最终只是源代码的东西......从代码生成/VM的角度来看,它们根本不重要。
在您的具体示例中,使用“int”不会创建垃圾。但是,如果创建的是对象,那么对于这两种情况,垃圾的数量和垃圾何时有资格进行清理将是相同的。
采取以下代码:
public class X
{
public static void main(final String[] argv)
{
foo();
bar();
}
private static void foo()
{
for(int i=0;i<5;i++)
{
final int myFinalVariable = i;
}
}
private static void bar()
{
for(int i=0;i<5;i++)
{
int myFinalVariable = i;
}
}
}
编译器为每种方法生成相同的字节码:
public class X extends java.lang.Object{
public X();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: invokestatic #2; //Method foo:()V
3: invokestatic #3; //Method bar:()V
6: return
private static void foo();
Code:
0: iconst_0
1: istore_0
2: iload_0
3: iconst_5
4: if_icmpge 15
7: iload_0
8: istore_1
9: iinc 0, 1
12: goto 2
15: return
private static void bar();
Code:
0: iconst_0
1: istore_0
2: iload_0
3: iconst_5
4: if_icmpge 15
7: iload_0
8: istore_1
9: iinc 0, 1
12: goto 2
15: return
}
由于声明变量的顺序,添加另一个在循环外声明变量的方法会为您提供稍微不同的字节码)。请注意,此版本不能将变量设为最终版本。最后一个版本不是最好的方法(如果可以的话,循环内的最终变量是最好的):
private static void car()
{
int myFinalVariable;
for(int i=0;i<5;i++)
{
myFinalVariable = i;
}
}
private static void car();
Code:
0: iconst_0
1: istore_1
2: iload_1
3: iconst_5
4: if_icmpge 15
7: iload_1
8: istore_0
9: iinc 1, 1
12: goto 2
15: return
}
正如回答的那样,是的,您确实可以将循环中的变量标记为“最终”。这是这样做的效果(Java 7、Eclipse Indigo、Mac OS X Lion)。
for ( int i = 0; i < 5; i++ ) {
// With 'final' you cannot assign a new value.
final int myFinalVariable = i; // Gets 0, 1, 2, 3, or 4 on each iteration.
myFinalVariable = 7; // Compiler error: The final local variable myFinalVariable cannot be assigned.
// Without 'final' you can assign a new value.
int myNotFinalVariable = i; // Gets 0, 1, 2, 3, or 4 on each iteration.
myNotFinalVariable = 7; // Compiler is OK with re-assignment of variable's value.
}
在循环内声明的变量仅在循环的单次执行之前具有作用域。
在循环内将变量声明为 final 对循环内的变量没有任何影响,但是如果我们在循环外使用 final 修饰符声明变量,则分配给原始类型的值或分配给引用变量的 Object 不能更改。
在下面的示例中,前两个循环没有问题,两个循环都给出相同的输出,但第三个循环给出了编译时错误。
公共类测试{
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
final int j= i;
System.out.println(j);
}
for (int i = 0; i < 5; i++) {
int j= i;
System.out.println(j);
}
final int j;
for (int i = 0; i < 5; i++) {
j= i;
System.out.println(j);
}
}
}
如果我错了,请纠正我。