java内存分配中的栈与堆

  一、首先,JAVA中数据存储的几块区域:

1、寄存器:这是最快的保存区域,位于处理器内部,是需要由编译器分配,我们对此没有直接的控制权。

2、栈(stack):位于RAM区,存放基本数据类型的变量、对象的引用变量和局部变量。

3、堆(heap):位于RAM区,存放的是new创建出来的对象和数组。

4、常量池:存放字符串常量和基本类型常量(public static final)。

5、静态区:存放static关键字定义的静态成员。

6、非RAM区:磁盘等永久存储空间。

这里我们主要关心栈、堆、常量池!

二、其次,JAVA程序中几种不同变量的存储方式:

1、实例变量(成员变量、属性):类中定义且方法之外的变量,成员变量存放于堆中的对象里,由垃圾回收机制处理。

2、局部变量:方法内或语句块中定义的变量,形式参数也属于局部变量,存放在栈中,必须初始化局部变量,它随着方法的调用结束而自动消失。

3、引用变量:对象的别名,存放在栈中,当新建一个对象或数组时,栈中就会分配一个引用变量,它的值为堆中对象或数组的首地址,以后访问对象就是通过引用变量的地址指向来找到对象的。当对象的调用结束时,引用变量的指向自动消失,而此时对象或数组没有变量引用时,不会自动消失,而会占用内存,成为垃圾,在未来的一个不确定时间里被垃圾回收器释放掉。

三、常量池:一般存放字符串常量,字符串对象的引用变量都是存储在栈中,如果是编译期创建好了的(就是通过双引号直接赋值),就存放在常量池中,如果通过new创建的,就存放在堆中的对象中。例如:

方式一:String  s1="abc";

方式二:String s2=new String(“abc”);

方式一是先在栈中创建一个String类的引用变量s1,然后查找堆中常量池有没有存放"abc",如果没有,则创建String类的对象,将"abc"存放进常量池,并令s1指向”abc”,如果已经有”abc” 则直接令s1指向“abc”;因此:

若问方式一创建了几个对象?准确答案:0或1

方式二是用new()来新建对象的引用变量s2,对象存放在堆中,引用变量存放在栈中。每调用一次就会创建一个新的对象,会分配不同的地址给引用变量。 因此:

若问方式二创建了几个对象?准确答案:1或2,因为当new产生一个字符串常量时,先去常量池中查找有没有该常量对象,若没有,就会在常量池中创建此字符串对象,并且赋值,同时在堆中会创建此字符串对象的一个拷贝对象(因为每次new都会在堆中创建一个对象);若查找有该常量,则不会在常量池中创建,而直接在堆张创建拷贝。

四、栈与堆的区别比较

1、栈

优点:存取速度快,栈中数据可以共享(就是多个变量指向同一个数据时,改变任何一个变量的指向,不会影响其他变量指向该数据)

缺点:栈中数据的大小和生存期是固定的,缺乏灵活性(栈中存储的都是局部变量和引用变量,属于基本类型,大小固定;在方法行为结束时会自动消失,生存期有限)

2、堆

优点:系统自动分配内存大小和生存期

缺点:存储速度慢

(暂时就总结这么点吧)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值