黑马程序员技术交流社区

标题: 堆内存/栈内存 [打印本页]

作者: 史卫平    时间: 2011-9-1 19:41
标题: 堆内存/栈内存
堆栈(stack):内存总是向一个方向增加或向相反方向减少,这个内存区用于存放方法或块中声明的局部变量。遇到局部变量声明时(包括调用方法中的变元变量-通C中的形参)内存增长,退出方法或块时这些变量弹出堆栈。
堆(heap):用于存储对象,对象的引用放在堆栈区,但是对象的数据区必须存放在堆中。堆是内存单元构成的一个巨大的表。New语句生成新对象时,保留的小块内存单元随时进行分配,一个内存单元块不再被现有变量引用时,这些不用的单元被释放和收集起来。理解起来费劲

堆内存存放的有:String、基本数据类型、对象引用、static静态代码块等
栈内存存放的有:StringBuffer、对象等。存放位置可以自定义吗,如果不能,那了解他有什么意义
栈是存放函数调用过程中的临时变量的! 堆是程序运行过程中动态申请的内存的存放处的!比如new的对象就在堆上


栈由寄存器直接操作,速度快;堆内可自由分配,内存量大,也可会放在虚拟内存当中,访问速度较慢。

堆内存是指存放的数据信息等“先进先出”,即取用先前存放的数据之后才能取用后面的,而栈内存恰好相反,即“先进后出”。上学的时候听老师讲过,不过java程序怎么看不出来什么先进先出

了解堆栈对程序开发又有什么帮助

上面是我从网上找的一些信息,有没有谁这方面比较了解的,期待李叶式的答案
作者: 李叶    时间: 2011-9-2 02:36
额…看到你这么信任我,突然间感觉好大的鸭梨~呵呵
其实吧,对你提出的这些技术问题,现在的我也不是特别了解
所以,在这里我就随便聊聊吧~一面之词,小心别被我忽悠了,呵呵

在你的问题中,其实有一个问题问的很关键,那就是:了解堆栈对程序开发有什么帮助
我的答案是:如果你从事Java行业,并且从事的是应用级开发的话,比如说编写软件或者开发网站之类
那基本上是没有什么帮助的
因为Java之所以能够成为当今主流编程语言之一,很重要的一个原因就是它简单,灵活,易懂,安全
Java不像C语言,如果你从事的是C语言开发,那么对于内存空间的使用和分配这些细节,你就必须要掌握的非常清楚,因为在C语言中,内存的分配和释放都是必须由你手动来进行的
而在Java中,由于Java已经把如何操作内存,以及如何分配和释放内存等等这些很多很多细节都给你封装好了,所以,你只需要学会如何去使用就可以了,而不需要特别关心内存是如何被分配的

其实在这里,也就体现出了学习Java时最重要的能力之一
那就是:你必须要学会从更高层次的角度去看待一件事物,并且只关心那些你需要去关心的细节
这句话要如何去理解呢?我们还是先打一个比喻吧:

假设你现在眼前摆着一台笔记本电脑,那么在你的眼中它是什么?
答案很简单:它当然就是一台笔记本电脑
恭喜你!你没有把它看成是一堆由金属零件和塑胶外壳所组合起来的物体~
这就说明你已经学会从更高层次的角度去看待一件事物了

然后,你会关注它的什么呢?
你应该只会关注它的显卡型号、内存大小、CPU频率,以及硬盘空间等等配置参数吧?
那么再次恭喜!你没有去关心CPU的每个针脚是干什么用的,主板上各个零件是如何互相通信的这样的细节
说明你已经学会只去关心那些你需要去关心的细节了

现在想一想,你为什么会把它看成是笔记本电脑,并且只去关心配置参数这些细节呢?
答案很简单,因为如果你想要使用这台笔记本电脑的话,你只需要把它当做笔记本电脑来使用就可以了
并且,它的CPU、内存、显卡等配置会在你使用它的过程中产生影响,所以你才需要关心它们
而像CPU每个针脚是干什么用的这样的细节,虽然可以让你对笔记本电脑的工作原理有更深入的认识
但是,这些知识对你使用这台电脑有任何帮助吗?显然没有~
你反而会因为关注了太多这样的细节,从而把脑子搞的更加混乱

所以,当你在Java中创建并使用一个对象的时候
假设你使用的就是一个Computer对象,那么你只需要去把它当做Computer对象来使用就可以了
由于这个Computer对象中的属性和方法会在你使用它的过程中产生影响,所以你才需要关心它们
而像这个Computer对象中的每个属性在堆空间栈空间中是如何保存的这样的细节,虽然可以让你对对象的存储和运行机制有更深入的认识
但是,这些知识对你使用这个Computer对象有任何帮助吗?显然没有~

所以,当你在学习Java的时候
与其去抠内存中堆和栈是以什么形式被分配的这样的细节
不如去多了解一下Java的垃圾回收机制,以及对象分配机制来的更实际些
也就是说,你更应当了解的是Java是如何工作的,而不是内存是如何工作的

所以,当你看待一件事物时
你只需要把它当做一个整体来看待
并且只去关注你需要去关注的细节
其他的细节一概可以忽略掉的这种思想
其实就叫做面向对象的思想

Tips:额……不知不觉说了这么多,我才发现我原来是这么的能白活……
不过,如果要想在Java这条路上有所建树的话,是必须要对面向对象的思想理解非常深刻的
其实,我上面的话也只是从某一个角度简单解释了一下面向对象思想的冰山一角……
真正的面向对象思想,是需要你在以后学习和工作的过程中,不断的思考和积累才能真正形成的~
好了,说了这么多,其实基本上一个技术性问题也没解答,但是或许还是应该会对你有一些启发吧~

[ 本帖最后由 李叶 于 2011-09-02  03:10 编辑 ]
作者: 匿名    时间: 2011-9-2 07:35
你是老师吗?不当老师亏了
作者: 匿名    时间: 2011-9-2 08:16
精辟啊。。。。。。。
作者: 匿名    时间: 2011-9-2 09:21
[quote] 原帖由 [i]史卫平[/i] 于 2011-09-02 07:35 发表 [url=http://bbs.itheima.com/redirect.jsp?goto=findpost&pid=8749&ptid=1342][img]http://bbs.itheima.com/images/common/back.gif[/img][/url]你是老师吗?不当老师亏了 [/quote]
不是老师~目前就是一个小程序员嘿嘿~
老师的话目前还不敢想额~呵呵,我的积累不够,所以随便讲讲这些基础和思想还行,但也还是有很多很多要学习的呢~
其实我还是挺笨的……
因为理解能力差,所以只有自己给自己讲清楚,我才能真正明白
因为忘性非常大,所以只有设法把笔记写详尽,我才能日后想起
所以……我就成了一个非常啰嗦,但讲话还有点道理的人~
作者: 郭亚飞    时间: 2011-9-2 10:41
我也是昨天才学习了张老师关于栈内存和堆内存的讲解视频,给大家分享一下学习体会,请多多指教!
关于栈内存和堆内存,我是这么理解的:  
Java把内存划分成两种:一种是栈内存,一种是堆内存。
  栈内存:在函数中定义的一些基本类型的变量和对象的引用变量都是在栈内存中定义和分配的,当某个函数被调用时,这个函数会在栈内存中申请一个空间,之后这个函数内部定义的变量,都会被分配到这个函数所申请到的栈空间,当函数运行结束时,分配给函数的栈空间被收回,在这个函数中定义的变量也随之被释放消失。
  堆内存:通过new这样的关键字创建的数组或者对象都分配到堆内存中,堆内存中分配的这些内存,由java虚拟机的垃圾自动回收器来管理。
  在堆中产生的一个数组或对象后,我们还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于这个数组或对象在堆内存中的首地址,栈中定义的这个变量就成了数组或对象的引用变量,我们以后就可以在程序中直接使用栈中的变量来访问我们在堆中分配的数组或对象了。在栈中分配的引用变量就相当于堆中分配的数组或者对象的一个名称或者代号。
  引用变量是一个普通的变量,定义时在栈中分配,引用变量在程序运行到它的作用域之外的时候,就被释放了,而我们的数组和对象,本身是在堆中分配的,即使程序运行到使用new产生这个数组或对象的语句所在的函数或者代码块之外,我们刚才产生的数组和对象,也不会释放,数组和对象是在没有引用变量指向它,即没有任何引用变量的值等于它的首地址时,它才会变成垃圾,不能再被使用,但仍然会占据内存空间,在随后一个不确定的时间,被垃圾回收器收走。
[ 本帖最后由 郭亚飞 于 2011-09-02  10:53 编辑 ]




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2