前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何给女朋友讲明白:Java中Stack(栈)与Heap(堆)

如何给女朋友讲明白:Java中Stack(栈)与Heap(堆)

原创
作者头像
淡定的蜗牛
修改2019-09-09 18:30:14
4740
修改2019-09-09 18:30:14
举报
文章被收录于专栏:Java知己Java知己

背景


Java中Stack(栈)与Heap(堆)是面试中被经常问到的一个话题。

有没有对Java中Stack(栈)与Heap(堆)烂熟于心的童鞋,请举手!!!(怎么没人举手...)

这个时候蜗牛哥的对象弱弱的举起了小手(这个对象不是new出来的哈)

女朋友:牛哥,谁要怼咱呀?我要不要先打个摇摇灵?

蜗牛哥:Heap(堆)与Stack(栈)是两种内存区域,不是要干架(没文化真可怕....)

蜗牛哥:今天就来给你讲讲Java中Stack(栈)与Heap(堆)到底是什么?

女朋友:好呀,好呀,搞明白了堆与栈,我是不是就是Java高级工程师了?

蜗牛哥:有牛哥在,你还怕搞不明白???

女朋友:嘻嘻,我已经拿好我的小本本准备好记笔记了

蜗牛哥:好的,那咱们这就开讲

正是金九银十跳槽季,为大家收集了2019年最新的面试资料,有文档、有攻略、有视频。有需要的同学可以来在公众号【Java知己】,发送【面试】领取最新面试资料攻略!

什么是Stack(栈)内存?


Java中的Stack(栈)是内存的一部分,包含方法、局部变量和引用变量。Stack(栈)内存始终以 后进先出 顺序引用。在Stack(栈)内存中创建局部变量。

什么是Heap(堆)内存?


Heap(堆)是包含对象的内存部分,也可能包含引用变量。实例变量在Heap(堆)内存中创建。

Java中的内存分配


JVM将内存划分为以下部分。

  1. Heap(堆)
  2. Stack(栈)
  3. Code(代码)
  4. Static(静态)

这种内存划分是有效管理内存所必需的。

  • Code(代码) 内存包含所有您的字节码
  • Stack(栈) 内存包含所有方法、局部变量和引用变量。
  • Heap(堆) 内存包含对象 (也可以含有引用变量)。
  • Static(静态) 内存包含静态数据/方法

本地和实例变量之间的区别


变量实例被声明在类中但不包含方法内变量

代码语言:txt
复制
class Student{ 
    int num; // num为实例变量
    public void showData{}

局部变量被定义在方法内部,包含方法参数。

代码语言:txt
复制
public void sum(int a){
int x = int a + 3;
// a,x是局部变量;
}

栈和堆之间的区别


让我们举个例子来更好地理解这一点。

考虑一下你的main方法调用方法m1

代码语言:txt
复制
public void m1 {
int x = 20
}

在java栈中,将创建一个frame(栈帧)在方法m1中。

m1中的变量X也将在栈中为m1的frame(栈帧)中创建(见下图)。

方法m1调用方法m2。在java栈中,在m1的frame(栈帧)顶部为m2创建一个新栈帧。

变量b和c也将在栈中的栈帧m2中创建。

代码语言:txt
复制
public void m2(int b){
    boolean c;
}

同样的方法m2是调用方法m3。同样在栈顶部创建一个栈帧m3(见下图)。

现在假设我们的方法m3正在为类 “Account” 创建一个对象,它有两个实例变量int p和int q。

代码语言:txt
复制
Account {
    Int p;
    Int q;
}

这是方法m3的代码

代码语言:txt
复制
public void m3(){
    Account ref = new Account();
    // more code
}

语句new Account()将在堆中创建一个Account对象。

引用变量“ref”将在java堆中创建。

赋值“=”运算符将使引用变量指向堆中的对象。

一旦方法执行完,控制流程将返回调用方法。在里的情况,就是返回到方法m2。

方法m3的栈将被刷新

由于引用变量ref将不再指向堆中的对象,因此它将符合垃圾回收的条件。

方法m2完成执行后。它将从堆栈弹出,其所有变量将被刷新,不再可用。

同样对于方法m1。

最终,控制流程将返回程序的起始点。通常,就是“main”方法。

如果对象有一个引用作为其实例变量怎么办?

代码语言:txt
复制
public static void main(String args[]) {
  A parent = new A(); 
  //more code 
} 

class A{ 
  B child = new B(); 
  int e;
  //more code 
} 
  
class B{ 
  int c; 
  int d;  
  //more code 
}

在这种情况下,引用变量“child”将在堆中创建,而堆又将指向其对象,如下图所示。

总结一下:

  • 调用方法时,会在栈顶部创建一个栈帧。
  • 一旦方法完成执行,控制流将返回到调用方法,并刷新其相应的栈帧。
  • 在栈中创建局部变量
  • 实例变量在堆中创建并且是它们所属对象的一部分。
  • 在栈中创建引用变量。

“不积跬步,无以至千里”,希望未来的你能:有梦为马 随处可栖!加油,少年!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 什么是Stack(栈)内存?
  • 什么是Heap(堆)内存?
  • Java中的内存分配
  • 栈和堆之间的区别
  • 如果对象有一个引用作为其实例变量怎么办?
  • 总结一下:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档