Java中堆和栈的理解

1、栈(stack)和堆(heap)都是java用来在内存中存放数据的地方。

2、栈
通过压栈和弹栈的方式进行存取,所以说存取速度快,仅次于位于cpu中的寄存器,但缺点是数据大小和生存期必须确定,缺乏灵活性。另外,栈数据可以共享。

栈中存放的数据为基本数据类型和对象的引用,都知道基本类型(primitive types), 共有8种,即int, short, long, byte, float, double, boolean, char。这种类型的定义是通过诸如int a = 3; long b = 255L;的形式来定义的,称为自动变量。自动变量存的是字面值,不是类的实例,即不是类的引用,这里并没有类的存在。如int a = 3; 这里的a是一个指向int类型的引用,指向3这个字面值。这些字面值的数据,由于大小可知,生存期可知(这些字面值固定定义在某个程序块里面,程序块退出 后,字段值就消失了),出于追求速度的原因,就存在于栈中。
另外,栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设定义
int a = 3;
int b = 3;
  编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处 理int b = 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况。
  
3、堆
可以动态的分配内存大小,生存期也不必告诉编译器,java的垃圾回收器会自动收回不再使用的的内存空间。但缺点是,在运行时需要动态分配内存,存取速度慢
堆中存放的是包装类数据,如Integer, String, Double等将相应的基本数据类型包装起来的类。Java用new()语句来显示地告诉编译器,在运行时才根据需要动态创 建,因此比较灵活,但缺点是要占用更多的时间。

4、在JAVA中,有六个不同的地方可以存储数据:
1. 寄存器(register)。这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部。但是寄存器的数量极其有限,所以寄存器由编译器根据需求进行分配。你不能直接控制,也不能在程序中感觉到寄存器存在的任何迹象。
2. 堆栈(stack)。位于通用RAM中,但通过它的“堆栈指针”可以从处理器哪里获得支持。堆栈指针若向下移动,则分配新的内存;若向上移动,则释放那些 内存。这是一种快速有效的分配存储方法,仅次于寄存器。创建程序时候,JAVA编译器必须知道存储在堆栈内所有数据的确切大小和生命周期,因为它必须生成 相应的代码,以便上下移动堆栈指针。这一约束限制了程序的灵活性,所以虽然某些JAVA数据存储在堆栈中——特别是对象引用,但是JAVA对象不存储其 中。
3. 堆(heap)。一种通用性的内存池(也存在于RAM中),用于存放所以的JAVA对象。堆不同于堆栈的好处是:编译器不需要知道要从堆里分配多少存储区 域,也不必知道存储的数据在堆里存活多长时间。因此,在堆里分配存储有很大的灵活性。当你需要创建一个对象的时候,只需要new写一行简单的代码,当执行 这行代码时,会自动在堆里进行存储分配。当然,为这种灵活性必须要付出相应的代码。用堆进行存储分配比用堆栈进行存储存储需要更多的时间。
4. 静态存储(static storage)。这里的“静态”是指“在固定的位置”。静态存储里存放程序运行时一直存在的数据。你可用关键字static来标识一个对象的特定元素是静态的,但JAVA对象本身从来不会存放在静态存储空间里。
5. 常量存储(constant storage)。常量值通常直接存放在程序代码内部,这样做是安全的,因为它们永远不会被改变。有时,在嵌入式系统中,常量本身会和其他部分分割离开,所以在这种情况下,可以选择将其放在ROM中
6. 非RAM存储。如果数据完全存活于程序之外,那么它可以不受程序的任何控制,在程序没有运行时也可以存在。
就速度来说,有如下关系:
寄存器 < 堆栈 < 堆 < 其他

简单记忆

堆:放new出来的对象
栈:放基本类型数据和对对象的引用(相当于指针,但是对象本身还是在堆里)
常量池:public static final存放字符串常量和基本类型的常量
静态域:放静态成员 static定义的

对速度来讲,栈比堆快
栈的回收机制:当程序块结束,基本数据类型不被使用,就自动销毁了
堆的回收机制:是由虚拟机自动判断,即当某个对象不再使用,java垃圾回收器自动回收

https://www.cnblogs.com/iliuyuet/p/5603618.html

猜你喜欢

转载自blog.csdn.net/qq_42780864/article/details/81258303