资源描述:
《【精品】从“关于Java堆与栈的思考”一帖看错误信息的传播》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、从“关于Java堆与栈的思考”一帖看错误信息的传播.txt如果我穷得还剩下一•碗饭我也会让你先吃饱全天下最好的东酋都应该归我所有,包括你!!先说喜欢我能死啊?别闹,听话。有本事你就照顾好口己,不然就老老实实地让我來照顾你!我对转贴的信息一冇•有敌意,原因如下:首先,除了制造更多的信息垃圾,转贴不会带來新的价值,想收藏的话一个链接足矣;其次,将错误信息以讹传讹,混淆视听。不妨选一个典型的例子说明一二。相信《关于Java堆与栈的思考》这个帖子大家并不陌生,转载量极大。但内容如何呢?我就试着分析一下。说明:以下内容,黑色字体为引用别人的帖子,红色字体是我的分析,蓝
2、色字体是引用相关文献。1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。与C++不同,对于堆来说是有道理的。但C++的栈也是由编译器负责安排和布局的,这和java没什么区别。其实,java里提到的堆和栈应该是逻辑层而上的,是jvm划分的,并不同于C++的实际运行时内存,因此根本不是一个层而上的东西,最好不要进行比较。2.栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享,详
3、见第3点。堆的优势是可以动态地分配内存大小,牛存期也不必事先告诉编译器,Java的垃圾收集器会口动收走这些不再使用的数据。但缺点是,「IT于耍在运行时动态分配内存,存取速度较慢。在逻辑上看,可以认为栈比堆快,但是请不要和寄存器比。上而己经提到,java所谓的堆和栈是逻辑上的,《TheJavaVirtualMachineSpecification》中,将运行时数据区分为pc寄存器、java虚拟机栈、堆、方法区、运行时常量池、木地方法栈共6个部分,而CPU中的寄存器是物理实体。比如jewa执行一个加法操作,逻辑上看是读取栈顶的两个数据,执行加法,将结果写回栈顶,
4、但实际的代码经过jvmjit编译之后很可能就是在寄存器屮执行加法。因此逻辑意义上的比较根本没有什么价值。〃栈数据可以共享〃,这个说法是该帖子〃创造性〃的提出來的。翻遍所有的java资料,根木找不到这样的说法(现在看来,也不全是,国内已经有书籍将这个帖子完全照搬了,抄袭可耻!貌似有本《java程序员面试宝典》,看过的都知道,呵呵)。3.Javarp的数据类型有两种。一种是基本类型(primitivetypes),共有8种即int,short,long,byte,float,double,boolean,char(注意,并没有string的基本类型)。这种类型的
5、定义是通过诸如inta=3;longb=255L;的形式来定义的,称为自动变量。值得注意的是,自动变量存的是字面值,不是类的实例,即不是类的引川,这里并没有类的存在。如inta二3;这里的a是一个指向int类型的引用,指向3这个字面值。这里混淆了一个问题。首先要知道什么是字面值,所谓的字面值是形如1,3,2.0,2.0f,'c',〃Hello〃这样的形式出现的常量。基本类型变量里存的是什么?值。存到变量中就不存在"字而值〃一说了!〃如inta=3;这里的a是一个指向int类型的引用〃,这个例子就太不恰当了,我们要注意的是,inta=3;我们得到的是一个空间,
6、里而存的是3这个数。这里又〃int类型的引用〃云云,岂不缪哉?这些字面值的数据,山于大小可知,生存期可知(这些字面值固定定义在某个程序块里面,程序块退出后,字段值就消失了),出于追求速度的原凶,就存在于栈中。基木类型的变量存在栈里或者堆里不是由〃大小可知,生存期可知〃就能确定了。关键是上下文。比如voidfunc(){inta=3;!这向然是存在栈里的。而classTest{inta=3;这就肯定是随对象放到堆甲的。因此,不要孤立的看到基木类型就说放到栈里,看到引用类型就说放到堆里。区分引用变量和对象本身特别重要,这个下而再说。另外,栈有一个很重要的特殊性,
7、就是存在栈中的数据可以共享。假设我们同时定义inta=3;intb=3;编译器先处理inta=3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字而值为3的地址,没找到,就开辟一个存放3这个字而值的地址,然后将a指向3的地址。接着处理intb=3;在创建完b的引川变量后,由于在栈屮已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况。特别注意的焰,这种字血值的引用与类对彖的引用不同。假定两个类对彖的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变杲也即刻反映出这个变化。相反,通过字面
8、值的引川来修改其值,不会导致另一个指向此字面值的引用