【java】大白话理解堆内存和栈内存 您所在的位置:网站首页 java中什么是堆和栈 【java】大白话理解堆内存和栈内存

【java】大白话理解堆内存和栈内存

2024-07-03 02:37| 来源: 网络整理| 查看: 265

一直搞不懂堆内存和栈内存,就先写这个文章暂记一下当前的理解叭,后面有新的理解的时候再补充

一、概述

JAVA在程序运行时,在内存中划分5片空间进行数据的存储。分别是:1:寄存器。2:本地方法区。3:方法区。4:栈。5:堆。

可以把堆理解为一家餐厅,里面有200张桌子,也就是最多能同时容纳200桌客人就餐,来一批客人就为他们安排一些桌子,如果某天来的客人特别多,超过200桌了,那就不能再接待超出的客人了。

当然,进来吃饭的客人不可能是同时的,有的早,有的晚,先吃好的客人,老板会安排给他们结账走人,然后空出来的桌子又能接待新的客人。

这里,堆就是餐厅,最大容量200桌就是堆内存的大小,老板就相当于GC(垃圾回收),给客人安排桌子就相当于java创建对象的时候分配堆内存,结账就相当于GC回收对象占用的空间。

接着把栈比作一口废井,这口井多年不用已经没水了,主人现在把它作为贮存自酿酒的地方,存酒的时候就用绳子勾着酒坛子慢慢放下去,后面再存就一坛一坛堆着放上去,取酒的时候就先取最上面的坛子。

二、堆内存、栈内存

堆内存: 存放由new创建的数组和对象(包括对象中的实例变量,也就是对象的属性) 栈内存: 存放基本类型的变量和对象的引用变量(放的不是引用变量的值,是引用变量的地址,真正的值在堆内存中)

在这里插入图片描述

三、堆和栈的区别

JVM是基于堆栈的虚拟机,JVM为新创建的线程都分配一个堆栈,也就是说,对于一个java程序来说,它的运行就是通过堆栈的操作来完成。堆栈以帧为单位保存线程状态,JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。 差异: 1、堆内存用来存放由new创建的对象和数组 2、栈内存用来存放方法或者局部变量等 3、堆是先进先出,后进后出 4、栈是先进后出,后进先出 5、共享性不同: (1)栈内存是线程私有的 (2)堆内存是所有线程共有的 6、栈的速度要快,且栈内存的数据是可以共享的

int a = 3; //在栈中创建变量a然后给a赋值,先不会创建一个3 而是现在栈中找有没有3,如果有直接指向,如果没有就加一个3进来。 int b = 3 ; //首先也要创建一个变量b 四、补充

栈(stack):是一个先进后出的数据结构,通常用于保存方法(函数)中的参数,局部变量。 在java中,所有基本类型和引用类型都在栈中存储:栈中数据的生存空间一般在当前scopes内(就是由{…}阔起来的区域)。

栈: 函数中定义的基本类型变量,对象的引用变量都在函数的栈内存中分配。 栈内存特点,数据一执行完毕,变量会立即释放,节约内存空间。 栈内存中的数据,没有默认初始化值,需要手动设置

堆: 堆内存用来存放new创建的对象和数组。 堆内存中所有的实体都有内存地址值。 堆内存中的实体是用来封装数据的,这些数据都有默认初始化值。 堆内存中的实体不再被指向时,JVM启动垃圾回收机制,自动清除,这也就是JAVA优于C++的表现之一。 图解:

main() int x =1; show() int x= 2;

以上程序执行步骤: 第一步——main()函数是程序入口,JVM先执行,在栈内存中开辟一个空间,存放int类型变量x,同时赋值1;

第二步——JVM执行show()函数,在栈内存中又开辟一个新的空间,存放int类型变量x,同时赋值2;

此时main空间与show空间并存,同时运行,互不影响。

第三步——show()执行完毕,变量x立即释放,空间消失,但是main()函数空间仍然存在,main()中的变量x依然存在,不受影响。

在这里插入图片描述

五、练习

1、先自己想想结果

String str1 = "abc"; String str2 = "abc"; System.out.println(str1==str2); String str1 = "abc"; String str2 = "abc"; str1 = "bcd"; System.out.println(str1 + "," + str2); System.out.println(str1==str2); String str1 = "abc"; String str2 = "abc"; str1 = "bcd"; String str3 = str1; System.out.println(str3); String str4 = "bcd"; System.out.println(str1 == str4); String str1 = new String("abc"); String str2 = "abc"; System.out.println(str1==str2); String s1 = "ja"; String s2 = "va"; String s3 = "java"; String s4 = s1 + s2; System.out.println(s3 == s4); System.out.println(s3.equals(s4));

2、看看答案和你的一样吗?

String str1 = "abc"; String str2 = "abc"; System.out.println(str1==str2); //true String str1 = "abc"; String str2 = "abc"; str1 = "bcd"; System.out.println(str1 + "," + str2); //bcd,abc System.out.println(str1==str2); //false 虽然最开始 str1和str2都指向同一个变量abc但str1引用变化后不会改变str2的 String str1 = "abc"; String str2 = "abc"; str1 = "bcd"; String str3 = str1; System.out.println(str3); //bcd String str4 = "bcd"; System.out.println(str1 == str4); //true String str1 = new String("abc"); String str2 = "abc"; System.out.println(str1==str2); //false new在堆内存中新开了一个对象 String s1 = "ja"; String s2 = "va"; String s3 = "java"; String s4 = s1 + s2; //java 注意这个+号,java里面重载了+,其实调用了stringBuild,会new对象。 System.out.println(s3 == s4); //false System.out.println(s3.equals(s4)); //true 只是比较值

文章参考:https://zhuanlan.zhihu.com/p/529280783?utm_id=0



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有