什么是Java堆和栈?它们的区别是什么?代码举例讲解

Java堆和栈是Java运行时数据区域的两个重要组成部分。
堆(Heap)用于存储对象实例,是GC管理的内存区域。所有的对象实例以及数组都要在堆上分配。
栈(Stack)用于存储栈帧,是线程私有的内存区域,由JVM自动分配和释放。每个方法调用都会创建一个栈帧。

二者的主要区别如下:

  1. 存储数据类型:
    • 堆存储对象实例和数组。
    • 栈存储基本类型变量,对象引用和方法调用等。
  2. 生命周期:
    • 堆中的对象随着GC回收产生变化。
    • 栈中的数据随着方法调用进入和退出栈帧自动产生变化。
  3. 线程亲和性:
    • 堆中的对象可以被所有线程访问。
    • 栈中的数据仅供线程私有访问。
  4. 内存分配:
    • 堆上的内存动态分配,可以缩小或扩大。
    • 栈上的内存在编译时就已分配,进入方法时分配,退出方法时释放。

来看一个简单例子:
我们可以编写一个Java程序,观察对象和基本变量是存储在堆还是栈中。

public class Sample {
    public void method1() {
        int a = 10; // 存储在栈中  
        String b = "Hello"; // 对象引用b存储在栈中,对象"Hello"存储在堆中  
        final double c = 3.14; // 存储在方法区的字符串常量池中  
    }  

    public void method2() {
        long d = 100L; // 存储在栈中
        char e = 'a'; // 存储在方法区的字符串常量池中  
    }
}  

从这个简单示例可以看出:

  • 基本类型变量a、d存储在栈中。
  • 对象引用b存储在栈中,对应的对象实例”Hello”存储在堆中。
  • final常量c和char常量e存储在方法区的字符串常量池中。

所以,熟悉Java堆和栈的区别可以帮助我们更好地理解Java的内存管理和对象生命周期。