在循环内创build最终variables
这是允许在Java中:
for(int i=0;i<5;i++){ final int myFinalVariable = i; }
我的问题的关键字是final
。 它允许做一个最终的variables,随着循环的每一个运行而改变吗? 我想知道这是因为final说你不能改变variables的值(只调用myFinalVariable = i
),但是我用final int
重新定义了整个variables。
他们是两个完全不同的variables,只是具有相同的名称 – 循环的前一个运行的variables已经走向垃圾收集器的道路?
是的,这是允许的。 final
关键字意味着你不能在其范围内改变variables的值。 对于循环示例,您可以将循环底部的variables视为超出范围,然后使用循环顶部的新值返回到范围。 分配给循环内的variables将不起作用。
你是对的,对于循环中的每一次迭代,你正在创build一个新的variables。 variables确实共享相同的名称,但这很好,因为它们不在同一个范围内。 下一个例子不起作用:
final int myFinalVariable = 0; for(int i=0;i<5;i++){ myFinalVariable = i; }
variables只是堆栈中的一个位置。 尽量保持你的variables尽可能小,并尽量使它们最终。 然而,范围和最终只是源代码的东西…从代码生成/虚拟机的angular度来看,他们根本就不重要。
在你的具体例子中,使用“int”不会产生垃圾。 但是,如果是创build对象,那么对于这两种情况,垃圾的数量和垃圾何时有资格进行清理将是相同的。
采取以下代码:
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 }
由于声明了variables的顺序,因此添加另一个在循环外部声明variables的方法会给您稍微不同的字节码。 请注意,这个版本的variables不能做最终的。 这最后一个版本不是最好的方法(如果你能做到这一点,循环内的最后一个variables是最好的):
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 }
在循环内部声明的variables只有在循环的一次执行之前才有作用域。
在循环中将variables声明为final是对于循环中的variables没有区别,但是如果我们用final修饰符在循环外部声明variables,那么分配给基本types或分配给参考variables的Object的值不能更改。
在下面的例子中,前两个循环没有问题,两个循环都给出相同的输出,但是第三个循环给出了一个编译时间Error。
公共类testing{
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); } }
}
如果我错了,请纠正我。
如回答,是的,你确实可以将循环中的variables标记为“最终”。 这样做的效果(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. }