news 2026/2/15 16:50:05

<span class=“js_title_inner“>为什么会有 StackOverflow?栈和堆到底有什么区别?</span>

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
<span class=“js_title_inner“>为什么会有 StackOverflow?栈和堆到底有什么区别?</span>
关注我们,设为星标,每天7:30不见不散,每日java干货分享

在计算机的内存世界里,数据只有两个去处:
要么去栈 (Stack),要么去堆 (Heap)

虽然它们都叫“内存”,但待遇天差地别。
一个像是军队的内务,整齐划一,但空间狭小;
一个像是富豪的杂物间,随地乱放,空间巨大。

理解了它们,你就能听懂 Java 里的那句黑话:“对象在堆里,引用在栈里。”


💻 一、技术分析:秩序与自由的权衡

1. 栈 (Stack) —— 先进后出的“弹夹”

  • 特性:LIFO (Last In First Out)。就像一把手枪的弹夹,最后压进去的子弹,必须最先打出来。

  • 存什么:

  • 局部变量:int a = 10;

  • 方法调用链:main()funcA()funcA()funcB()

  • 管理:自动管理。函数执行完,系统自动“弹出”内存,不需要你操心。

  • 速度:极快。CPU 只需要移动指针(ESP)就能分配和回收内存。

  • 大小:很小(通常几 MB)。

2. 堆 (Heap) —— 自由散漫的“广场”

  • 特性:无序、动态。就像一个巨大的广场,你想在哪里搭帐篷就在哪里搭。

  • 存什么:对象 (Object)。凡是new出来的东西(new User(),new int[10000]),都在这里。

  • 管理:手动管理(C/C++ 需要free)或GC 管理(Java/Python 有保洁员)。

  • 速度:较慢。分配内存需要找空地,访问内存需要通过指针跳转。

  • 大小:很大(取决于你的物理内存,几 GB 甚至几十 GB)。


🎒 二、故事场景:收纳盒与杂物间

为了彻底搞懂这两者的关系,我们将内存比作你的家

1. 栈 (Stack) —— “放在手边的收纳盒”

  • 场景: 你坐在书桌前工作(执行函数)。

  • 规则: 书桌空间很小,你只能放最常用的东西。

  • 操作:

  • 函数调用: 你开始写作业 A。你在书桌上铺了一张纸(压栈)。

  • 嵌套调用: 作业 A 需要用到作业 B 的数据。你又拿出作业 B 的纸,盖在A 上面。

  • 再嵌套: 作业 B 需要作业 C。你把 C 的纸盖在B 上面。

  • 执行完毕: C 做完了,你把 C 的纸扔掉(弹栈),露出下面的 B。

  • 特点: 永远只能处理最上面那一层。非常有条理,绝对不会乱。

2. 堆 (Heap) —— “巨大的杂物间”

  • 场景: 你需要组装一辆自行车(创建一个大对象)。

  • 问题: 书桌(栈)太小了,根本放不下自行车。

  • 操作:

  • • 你走到宽敞的杂物间 (Heap),找块空地,把自行车组装好。

  • 关键步骤: 你回到书桌前,在纸上写下一行字:“自行车在杂物间 A 区 3 排”

  • • 这行字(内存地址/引用),是在栈里的。

  • • 自行车本身,是在堆里的。


💥 三、两大经典灾难

1. StackOverflowError (栈溢出)

  • 场景:无限递归

  • 故事:

  • • 你讲了个故事:“从前有座山,山里有座庙,庙里有个老和尚讲故事:‘从前有座山,山里有座庙...’”

  • • 你每讲一次,就往书桌上铺一张纸。

  • • 讲到第 10000 次时,书桌上的纸摞到了天花板,轰的一声倒了。

  • 原因: 函数调用层级太深,超出了栈的深度限制。

2. OutOfMemoryError (OOM - 堆溢出)

  • 场景:囤积癖

  • 故事:

  • • 你疯狂地买自行车(new Object),买一辆就扔进杂物间。

  • • 杂物间虽然大,但也有塞满的时候。

  • • 如果你光买不扔(没有被 GC 回收),最后杂物间连一只脚都插不进去了。

  • 原因: 创建了太多对象,且都在被使用,无法回收,把堆撑爆了。


🥊 四、巅峰对决:为什么需要两个?

维度

栈 (Stack)堆 (Heap)
比喻收纳盒杂物间
存储内容

局部变量、引用指针

new

出来的对象、实体

访问速度极快

(CPU亲儿子)

较慢

(需要查地址)

空间大小

(MB 级别)

(GB 级别)

生命周期

函数结束自动释放

等待 GC 回收

溢出报错StackOverflowErrorOutOfMemoryError

🎯 五、总结:指针的羁绊

在 Java/C++ 中,栈和堆不是割裂的,它们通过“引用” (Reference/Pointer)紧紧联系在一起。

User user = new User();

这行简单的代码,其实横跨了两个世界:

  1. 1.左边User user**: 是一个引用**(小纸条),存在里。

  2. 2.右边new User()**: 是一个对象**(大自行车),存在里。

  3. 3.=: 是一根红线,把栈里的纸条指向了堆里的自行车。

一句话总结:栈是运行时的单位(处理逻辑),堆是存储的单位(存放数据)。

推荐阅读 点击标题可跳转

50个Java代码示例:全面掌握Lambda表达式与Stream API

16 个 Java 代码“痛点”大改造:“一般写法” VS “高级写法”终极对决,看完代码质量飙升!

为什么高级 Java 开发工程师喜爱用策略模式

精选Java代码片段:覆盖10个常见编程场景的更优写法

提升Java代码可靠性:5个异常处理最佳实践

为什么大佬的代码中几乎看不到 if-else,因为他们都用这个...

还在 Service 里疯狂注入其他 Service?你早就该用 Spring 的事件机制了

看完本文有收获?请转发分享给更多人

关注「java干货」加星标,提升java技能

❤️给个「推荐 」,是最大的支持❤️

.cls-1{fill:#001e36;}.cls-2{fill:#31a8ff;}

.cls-1{fill:#001e36;}.cls-2{fill:#31a8ff;}

.cls-1{fill:#001e36;}.cls-2{fill:#31a8ff;}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/6 5:29:10

核心期刊拒稿率 90%?虎贲等考 AI:从选题到录用的学术加速器

“改了 6 版的论文,被 CSSCI 拒稿理由是‘创新点模糊’”“文献引用格式错乱,编辑部让返工 2 次”“实证数据缺乏支撑,审稿人直接打回重写”—— 学术发表路上,无数科研人陷入 “选题难、写作慢、录用率低” 的循环。普通 AI 工具…

作者头像 李华
网站建设 2026/2/14 20:37:23

ArkTS 声明式语法与状态管理入门

网罗开发(小红书、快手、视频号同名)大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方…

作者头像 李华