问题描述
- java循环体里边创建对象,它的执行过程是怎样的?
-
public class Test
{
public static void main(String[] args)
{
for(int i=0;i<10;i++)
{
Object obj = new Object();
}
}
}比如说上边这一段代码,越看越不对劲了,它难道是在main方法栈中先后创建了10个引用叫obj?然后每个obj指向不同的new出来的对象?
解决方案
单步调试下就知道了,正常的逻辑是这样的,可能编译器优化后一行代码都没有了。
可以反编译看下生成的字节码。
解决方案二:
一般是循环一次一个新对象,所以如非必要,不要在循环里面创建对象。
解决方案三:
它的确是在main方法栈中先后创建了10个引用叫obj,然后每个obj指向不同的new出来的对象。
关键是:每次循环体执行完后,循环体内定义的代码块局部变量、对象如果没有被继续引用,就立即被销毁了;即obj变量、new出来的对象都被销毁了。
解决方案四:
用内存角度来解释的话,在JVM的方法栈和堆内存这两个内存中,当运行Object obj = new Object();时,在方法栈的栈顶中放入Object obj,然后在堆中生成一个Object对象,最后方法栈中的obj指向Object对象,这时完成一次循环的内存动作。接着第二次循环, new Object();又产生一个新的Object对象,然后方法栈中的obj指向新的Object对象,第一次循环的Object对象没有被任务变量引用,成为了垃圾,等JVM垃圾回收器回收。其它循环以此类推了。
在这里我提一下题外话,JVM有个优秀的算法是,JVM的方法栈,一个方法的调用产生一个栈帧,这个栈帧在方法调用时计算出你有几个局部变量,这个计算会过滤作用域的,如你的循环后面再建立一个局部变量,那JVM认为只有一个局部变量,因为你的Object obj = new Object();在大括号内,出了大括号就没有了,所以只需要一个位置来存放局部变量即可,也就是说运行到大括号时用这个位置来执行代码,出了大括号后下一个局部变量就可以接着使用这个栈的这个位置来执行下面的代码了。