是否每次在循环中创建一个新变量?

时间:2016-08-23 06:49:06

标签: java

在以下示例中:

for(int i=0; i<10; i++) {
  int k;
}
  1. 循环体(即声明&#34; int k&#34;)是否会重复执行10次?

  2. 如果是这种情况,这是否意味着每次创建新变量k? (因为这&#34;一个类型后跟一个变量名&#34;格式定义为在JAVA中创建一个新变量,尽管变量名保持不变)

4 个答案:

答案 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创建对象。但即便如此,编译器也会优化其中一些。