这是允许在java中:
for(int i=0;i<5;i++){ final int myFinalVariable = i; }
我的问题的关键字是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."":()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 }