龙空技术网

Java知识回顾之堆和栈

怀揣梦想的软件开发老 107

前言:

此刻咱们对“java的堆和栈”大约比较珍视,朋友们都需要学习一些“java的堆和栈”的相关知识。那么小编同时在网络上汇集了一些对于“java的堆和栈””的相关知识,希望大家能喜欢,你们一起来学习一下吧!

在日常程序开发中,我们都知道Java程序都是运行在Java虚拟机上(JVM)的,程序中所有的方法、变量、常量、实例、静态存储都是由JVM在内存中进行分配的。

一、栈内存

主要用来存储线程执行过程中的局部变量(能否储存成员变量?),方法的返回值,以及方法调用上下文(对象的引用),是一种只能在一端(称为栈顶)对数据项进行插入和删除,它遵循先进后出的规则来存储数据。

疑问一:网上看了好多说栈数据可以共享。我的理解是:栈是线程私有的内存区域,每个线程都有一个栈,线程执行函数的时候,就会往这个栈里面压入一个栈帧,这个栈帧包含局部变量表和操作数栈,它是怎么做到数据共享的?

通俗一点来讲先进后出:比如我们买的羽毛球筒,工厂加工完成后,会一个一个将羽毛球压到筒中(最后压进的羽毛球会在最上部)(进栈),最后羽毛球达到我们手中后,我们会从上往下一个一个的取出(最上面的会先被我们给取出)(出栈)。这样说的话,大家应该能听的明白一点吧。

我们再用程序运行看下是否如我们上述描述的先进后出:

当我们在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,就会自动释放掉为该变量分配的内存空间(栈的作用域),它不会被GC管理。

栈内存中的数据(局部变量),没有默认初始化值,需要给赋值,不然在调用该变量的时候会提示

Initialize variable的错误。

二、堆内存

是在JVM启动时候自动分配的(看上一篇JVM内容),用来存放由new创建的对象和数组,用完后靠垃圾回收机制(GC)不定期自动销毁。

虚拟机中只有且只有一个堆,程序中所有线程都共享它,它的存取类型为管道类型,先进先出。

用例子简单说下栈和堆的关系(这方面可能理解不是很到位,大家若有意见可以下方评论共同探讨)

public static void main(String[] args) {

Car car = new Car();

car.wheel = "4";

Car car1 = new Car();

car1.seat = "12";

}

主函数先进栈,会在栈内存中开辟一个空间,存放car变量,同时在堆内存中也开辟一个空间,存放new Car()对象。我们知道内存存储数据的时候都是通过地址来体现的,所以会给Car这个实体分配一个内存地址:0x0011,把堆这个地址赋给栈中的car(引用变量),car就通过地址指向了Car这个实体。

在我们日常开发或面试的时候,经常会碰到java中equals和==的区别:

从上图,我们可以看到程序运行的结果:

1)对于==,int类型(8大基本数据类型)的比较结果输出为true,String类型的输出结果为false;

2)String类型通过equals比较结果为true.

m == n为true这个结果结果我们应该能容易理解,基本数据类型的变量在栈内存中存储的是实际的值,而a == b为false,是因为a和b是String类型的变量,是引用类型的变量,为非基本数据类型的变量,它存储的是对象的堆内存地址。a==b的比较实际上比较的是a和b对应的堆内存地址,它们指向的是不同对象。

equals操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。

栈内存中能否储存成员变量?

不能,因为当对象创建出来,实体存在于堆,对象的成员变量已经在堆上分配空间,但对象里面的方法是没有出现的,只出现方法的声明,方法里面的局部变量并没有创建。等到对象调用此方法时,方法中的局部变量才会在栈中创建,所以,方法中的局部变量是在栈内的。

标签: #java的堆和栈