在Java程序编写中,我们对实例化对象不会陌生,例如我们现在有这样一条实例化语句:
int []arr = new int [3];这条语句在内存中是如何存储的呢,这就涉及到“栈”和“堆”的概念。
栈内存:栈内存首先是一片内存区域,存储的都是局部变量,凡是定义在方法中的都是局部变量(方法外的是全局变量),for循环内部定义的也是局部变量,是先加载函数才能进行局部变量的定义,所以方法先进栈,然后再定义变量,变量有自己的作用域,一旦离开作用域,变量就会被释放。栈内存的更新速度很快,因为局部变量的生命周期都很短。
堆内存:存储的是数组和对象(其实数组就是对象),凡是new建立的都是在堆中,堆中存放的都是实体(对象),实体用于封装数据,而且是封装多个(实体的多个属性),如果一个数据消失,这个实体也没有消失,还可以用,所以堆是不会随时释放的,但是栈不一样,栈里存放的都是单个变量,变量被释放了,那就没有了。堆里的实体虽然不会被释放,但是会被当成垃圾,Java有垃圾回收机制不定时的收取。
根据栈的定义,方法进入栈后再定义变量,即方法和变量都会存储在栈中。上面提到的语句,main方法和变量arr都存储在栈中;而堆内存中存储的是数组和对象(数组也属于对象),即new建立的所有东西都存储在堆中。上面的语句中,右侧是一个实体,存储在堆中。因此整个过程:主函数进入栈,定义变量arr,接下来应该为arr赋值,而右侧是new建立的一个实体,new在堆中开辟出一个空间,然后给这个实体分配一个内存地址(内存的存储是通过地址来实现的,地址是一段连续的二进制)。数组都是有一个索引,数组这个实体在堆内存中产生之后每一个空间都会进行默认的初始化(这是堆内存的特点,未初始化的数据是不能用的,但在堆里是可以用的,因为初始化过了,但是在栈里没有),不同的类型初始化的值不一样。所以堆和栈里就创建了变量和实体。
那么栈和堆是怎么联系起来的呢,上一段我们知道了内存分配给堆一个地址,栈中的变量操纵数组的时候就是通过操纵地址,而不是直接改变数组,这种我们不再叫他基本数据类型,而叫引用数据类型。称为arr引用了堆内存当中的实体。(可以理解为c或c++的指针,Java成长自c++和c++很像,优化了c++)。
堆与栈的区别总结如下:
1.栈内存存储的是局部变量而堆内存存储的是实体;
2.栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;
3.栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。