浅谈对于堆和栈的理解

学习了有一阵子的数据结构了。但发现对于基础的数据结构还有好多概念不是很清晰,说明还有好多知识的盲区需要填补的。比如如果有人把堆和栈连起来说,那一般都是想说栈,可不是堆…现在就先来解决下堆和栈的区分吧。Java中的堆和栈有什么区别呢?

从他们的定义上面将,最简单的说法就是:

栈是先进的后出,堆是先进的先出

总体来说,有以下几个方面:

1.栈内存储的是局部变量,而堆内存储的是实体对象。
2.栈内存的更新速度高于堆内存,因为局部变量的生命周期很短
3.栈内存的声明周期一结束就会被释放,而堆内存会被Java的垃圾处理机制不定时的清理

我们首先来了解下JVM Java虚拟机的内存划分:
Java虚拟机其实就像是一个应用程序或者软件一样,在运行的时候都需要内存区域,所以JVM在运行时会自动开辟出一块内存区域,启动以后,自己再对这块区域进行更加详细地划分,有因为每一块区域处理问题的方式都不同,因此需要进行单独管理。

JVM内存中划分出来的主要五部分:
本地方法区、寄存器、方法区、栈内存、堆内存

栈内存

栈内存首先是一片区域,存储的是局部变量。局部变量分为两种情况:1.方法中定义的变量; 2.for循环中定义的变量,而且是先加载函数再进行局部变量的定义。所以是方法先进栈,然后再定义变量。量也有自己的作用域,一旦离开自己的做哦有那个域,变量就会被释放。栈内存的更新速度很快,因为局部变量的生命周期都很短。

堆内存

堆内存存储的是数组和对象,凡是在new里面建立的对象都是存在于堆中,因而堆中存放的都是实体(对象)。实体用于封装数据,而且一般都要封装多组数据(实体中有多个属性)。一旦某个数据消失了,对这个实体没有产生影响,实体还可以使用,所以堆是不会被释放的,但是栈和他不一样,栈里面存放的是单个的变量,变量被释放了就没有了。堆内的实体虽然不会被释放,但是会被当成垃圾,Java会对垃圾进行不定时的回收。

下面我们通过一个实例来进一步区分堆和栈的关系:
定义在主函数中的语句:

int []  arr = new int [3];

主函数先进入栈,在栈中定义一个变量arr,接下来为变量arr赋值,但是等式右边的不是一个变量或者具体的值,而是一个实体。实体是创建在堆里的,在堆里首先通过new关键字开辟出一块内存空间,内存在存储数据的时候都是通过地址来体现的,地址是一块连续的二进制,然后给这个实体分配一个内存地址。数组都有一个索引,数组这个实体一旦在堆内存中产生之后,数组的每一个空间都会进行默认的初始化(对实体进行初始化是堆的特点,在栈中没有),不同的类型初始化值不一样。

堆和栈的联系

例子中给堆分配了一个地址,然后把堆的地址赋给arr,arr就通过地址指向了数组,所以arr想操作数组只能通过地址,而不是将实体直接赋给他。这个我们不叫做基本数据类型,而是引用数据类型,即arr引用了堆内存中的实体。

如果int [] arr = null;且arr不做任何的指向,null的作用就是取消引用数据类型的指向。
当一个实体没有数据类型指向时,他在堆内存中的地址不会被释放,而是会被当作一个垃圾,在不定时被Java清理走,但是什么时候清理不一定。

你可能感兴趣的:(算法和数据结构)