zoukankan      html  css  js  c++  java
  • 如何给女朋友讲明白:Java 中 Stack(栈) 与 Heap(堆)

    背景

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

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

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

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

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

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

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

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

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

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

    什么是 Stack(栈)内存?

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

    什么是 Heap(堆)内存?

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

    Java 中的内存分配

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

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

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

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

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

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

    class Student{ 
    	int num; // num为实例变量
    	public void showData{}
    
    
    

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

    public void sum(int a){
    
    int x = int a + 3;
    
    // a,x是局部变量;
    
    }
    
    
    

    栈和堆之间的区别

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

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

    public void m1 {
    int x = 20
    }
    
    

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

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

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


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

    public void m2(int b){
    	boolean c;
    }
    
    


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


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

    Account {
    	Int p;
    	Int q;
    }
    
    

    这是方法 m3 的代码

    public void m3(){
    	Account ref = new Account();
    	// more code
    }
    
    

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

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

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

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

    方法 m3 的栈将被刷新

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

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

    同样对于方法 m1。

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

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

    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” 将在堆中创建,而堆又将指向其对象,如下图所示。

    总结一下:

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

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

    关注公众号:「Java 知己」,每天更新 Java 知识哦,期待你的到来!

    • 发送「1024」,免费领取 30 本经典编程书籍。
    • 发送「Group」,与 10 万程序员一起进步。
    • 发送「面试」,领取 BATJ 面试资料、面试视频攻略。
    • 发送「JavaEE 实战」,领取《JavaEE 实战》系列视频教程。
    • 发送「玩转算法」,领取《玩转算法》系列视频教程。

    这个对象到底如何才能 new 出来?在线等

  • 相关阅读:
    SQL CHECKOUT
    Adobe CS4 " Licensing for this product has expired " FIX!!!
    sizeof()用法汇总
    Command
    EXP_FULL_DATABASE,IMP_FULL_DATABASE,DBA,CONNECT,RESOURCE
    inet_addr函数处理IP地址需要注意的问题 (转)
    Oracle:外键关联导致数据无法删除
    三范式
    Wireshark界面上展开数据帧
    我的HTML学习记录(三)
  • 原文地址:https://www.cnblogs.com/java-friend/p/11555079.html
Copyright © 2011-2022 走看看