在以下示例中:
for(int i=0; i<10; i++) {
int k;
}
循环体(即声明&#34; int k&#34;)是否会重复执行10次?
如果是这种情况,这是否意味着每次创建新变量k? (因为这&#34;一个类型后跟一个变量名&#34;格式定义为在JAVA中创建一个新变量,尽管变量名保持不变)
答案 0 :(得分:2)
不,变量的内存存在于方法中,而不存在于循环中。您只能在循环内访问k
这一事实完全由编译器完成。
如果您要更改此代码:
public class X
{
public static void main(final String[] argv)
{
for(int i = 0; i < 10; i++)
{
int k = i * 2;
System.out.println(k);
}
}
}
然后运行javap -c X以查看您将看到的字节码:
0: iconst_0
1: istore_1 // i = 0
2: iload_1
3: bipush 10
5: if_icmpge 25 // i < 10
8: iload_1
9: iconst_2
10: imul
11: istore_2 // k = i * 2 < this is the key (see below)
12: getstatic
15: iload_2 // this gets k (see below)
16: invokevirtual #3
19: iinc 1, 1 // i++
22: goto 2
25: return
istore_2
将计算结果存储到堆栈中的第二个位置。 iload_2
获取堆栈中第二个位置的值。 (您可以看到说明here)
堆栈始终存在,将其视为一个方法能够访问某个部分的数组。
答案 1 :(得分:1)
循环体(即语句“int k”)是否会重复执行10次?
这完全取决于你的意思。有关的堆栈槽将开始用于k
,但它是在方法入口上分配的,而不是在循环入口上分配。
如果是这种情况,这是否意味着每次创建新变量k? (因为这个“一个后跟变量名称的类型”格式定义为在JAVA中创建一个新变量,尽管变量名称保持不变)。
变量由编译器创建。它占用的地址空间是在方法输入上创建的,见上文。
与评论中的某些声明相反,Java Virtual Machine Specification §2.6:
完全指明了这一点每次调用方法时都会创建一个新帧。当方法调用完成时,框架将被销毁,无论该完成是正常还是突然(它会抛出未捕获的异常)。帧是从创建帧的线程的Java虚拟机堆栈(第2.5.2节)中分配的。每个帧都有自己的局部变量数组(第2.6.1节),它自己的操作数堆栈(第2.6.2节),以及对当前方法类的运行时常量池(第2.5.5节)的引用。
答案 2 :(得分:0)
由于语句int k
仅声明变量(分配int块)并且未定义它,因此不会每次都创建新变量。
此外,局部变量的范围应尽可能小。因此,声明变量的唯一好方法是在while循环中。
如果您想要保存时钟周期,初始化变量时,例如int k = 3;
,以节省额外的时钟时间,您可以在while循环外声明,从而增加变量的范围。在这种情况下,每次都不会初始化变量。
答案 3 :(得分:-1)
是的,变量k
创建了10次。
但这对性能没有任何意义,因为Java编译器会知道这10个变量的使用不会重叠。因此,它可以为它重用相同的存储器(或寄存器)。
所以不要害怕创建很多变量,没关系。更害怕使用new
创建对象。但即便如此,编译器也会优化其中一些。