今天去一公司面试,问了这么个问题:为什么要设堆区和栈区?
我说栈区是存放程序的局部变量、基本数据类型变量和引用类型变量的引用,在变量生命周期结束后系统会自动释放这部分内存。
但是堆区是存放对象引用的实体,系统不会自动释放这些空间,要么程序员手动释放,要么像java这样的垃圾回收机制。
但是貌似面试官还是不满意这个回答,他说我们也可以把局部变量放到堆区啊,我们自动释放不就行了......
求大牛指点?这两者的本质区别,或者说当初要设这俩区的初衷是什么?
------解决方案--------------------
不知道面试出这种题目是出于什么目的?纯粹让你答不好?
要问Java为什么要堆栈,那就要问C为什么要堆栈,问C为什么要堆栈就要问以前写汇编的为什么写着写着就喜欢把内存分两块来用,至于这个问题你跑去C板块和汇编板块估计都没几个人能让你信服地说清楚原因,我不是专门写C和汇编的,但至少用8051汇编写了很多程序,用x86汇编练了手,所以只简单说说我的看法。
首先汇编里,变量的概念几乎没有了,有的只是各种内存地址,不管是实地址还是虚地址,你访问一个变量就是靠地址,所以如果你不记住一个变量的地址,你就没办法去操作它,这就产生了问题,如果你的程序要1000个变量,你就把他们的地址全记下来吗?这显然是不现实的,首先这会浪费很多空间,因为几乎任何操作都离不开操作变量,也就是地址,那么就相当于你要用两倍甚至更多的空间来表示你的程序,而一半浪费在地址上,其次这样写程序也是没有效率的,1000个变量,难道你能把他们的地址全背下来吗?或者说当你看到地址0x1234的值赋值给地址0x2345时,你如何记得起0x1234和0x2345是两个干什么用的变量?
所以以一种系统的方法管理内存就显得尤为重要,毕竟我们要用计算机来方便自己,而不是拿来自虐。经过很多人的摸索,人们发现变量主要是两种形式,一种内容短小(比如一个int整数),需要频繁访问,但是生命周期很短,通常只在一个方法内存活,而另一种内容可能很多(比如很长一个字符串),可能不需要太频繁的访问,但生命周期较长,通常很多个方法中可能都要用到,那么自然将这两类变量分开就显得比较理性,一类存储在栈区,通常是局部变量、操作符栈、函数参数传递和返回值,另一类存储在堆区,通常是较大的结构体(或者OOP中的对象)、需要反复访问的全局变量。
堆区就是各种慢,申请内存慢,访问慢,修改慢,释放慢,整理慢(或者说GC垃圾回收),但优点也不言而喻,访问随机灵活,空间超大,在不超可用内存的情况下你要多大就给多大。
栈区就像临时工,干完就跑,所以超快,但是缺点也很多,比如生命周期短,一般只能在一个方法内存活,又比如你需要事先知道需要多大的栈(事实上绝大多数语言栈区要分配的大小编译期就确定了,Java就是这样),而且通常最大栈区可用内存都很小,你不可能往栈区里堆很多数据。
总之还是觉得面试Java程序员死扣这个问题,只能说明他们自己有问题,如何当做一个讨论来考考面试者知识面是否广阔还行,真当技术问题来像模像样地考是不是脑子烧了?