黑马程序员技术交流社区
标题:
关于其中的一个语句在栈内存和堆内存怎么展示的?
[打印本页]
作者:
栗俊植
时间:
2013-4-11 00:32
标题:
关于其中的一个语句在栈内存和堆内存怎么展示的?
本帖最后由 栗俊植 于 2013-4-11 01:22 编辑
class Test {
int num = 3;
public static void main(String[] args) {
Test t = new Test();
t.num = 5;
method(new Test());//这一步的匿名对象在栈内存和堆内存中是怎样展示的,怎样的过程?知道的分布详细讲解一下,谢谢了!
System.out.println(t.num);
}
public static void method(Test t){
t.num = 6;
}
}
复制代码
作者:
柳 德 彬
时间:
2013-4-11 01:01
需要知道两点
1. 堆中存放具体数据 栈中存放你所命名的变量名字(对象引用)
2. 既然叫匿名对象 自然没有名字 所以这就是在堆里有具体数据 而栈中没有名字指向这个数据的意思
作者:
张先龙
时间:
2013-4-11 01:01
虽然method是个静态方法,但是,该new Test()是具有另外的内存空间,method(new Test())得到的是对象的引用,并没有在静态方法的对内存中为它分配空间。在method处理之后,test的实例还是存在,一直到和test相关的程序体结束才消亡。所以是new Test()这个对象会存在内存当中,但是,不会存在给method静态方法划分的内存当中,method只是使自己的Test test声明指向了该对象,获得了该对象的引用。
作者:
栗俊植
时间:
2013-4-11 01:09
张先龙 发表于 2013-4-11 01:01
虽然method是个静态方法,但是,该new Test()是具有另外的内存空间,method(new Test())得到的是对象的引用 ...
谢谢 基本已经了解!
作者:
栗俊植
时间:
2013-4-11 01:21
class Test {
int num = 3;
public static void main(String[] args) {
Test t = new Test();
t.num = 5;
method(new Test());// 在栈内存有一个method() 指向开辟在堆内存的成员变量int num =3
// method()方法内t.name=6进行赋值 这事 num = 6 然后method()方法弹栈.
// 指向就断了, num = 6 也就成了堆内存的垃圾等待回收!
System.out.println(t.num);
}
public static void method(Test t){
t.num = 6;
}
}
复制代码
自己也查阅了资料,了解到是这样的一个过程!如果有不合理的地方,希望明白的高手给予改正!谢谢 同时谢谢对本题解答的所有人!
作者:
HM马明宇
时间:
2013-4-11 01:59
好好给你讲讲,嘿嘿!对于其中某些细节不必深究,知道有这回事就好,它们固然是有原因的,计算机发展这么多年,总有些规定有其特有原因,谁又能完全都知道呢!
计算机怎么储存数据的?
计算机是个二进制机器,我们知道电流具有磁效应,通过电路的开关可以改变一个小磁针的N极所指示的方向,这些都知道吧?如果不知道,真得滚去百度了!!!!
通过磁盘,磁盘上的磁道中的小磁粒的不同指向,代表0和1,这里的一个0或1代表数据存储单位中的一个位,通过这些小磁针的不同排列,就能表示信息,就跟DNA表示信息的方式类似,通过不同的排列表示信息,所有的文件就这样被储存了~~
数字在计算机上怎么表示知道吗?byte 类型最大才可以表示2的7次方减一是127,这是有原因的!
因为,早起的计算机科学家们规定了八个位表示一个字节byte ,想想一下,一个字节不就可以表示一个二进制的数字了吗?
是的,你应该能想到最大的数字是二进制的 11111111对吧,这个数换算成十进制是255,为什么不是127呢?
因为人类社会中有负数,所以java规定,最高位表示正负,位是从右往左看的,所以左边第一位是最高位,很不幸,最高位为1时,表示负数,所以byte类型的正数最大值只能是01111111,换算成十进制就是127!
想想看,127加1的二进制表示是什么?定义一个byte类型的数据,让它的值“等于”128,然后打印出来,然后很惊讶,然后想想,然后明白,然后恍然大悟 ~_~
然后,就有了short、int、long、各种编码方式、文本文件、各种文件,然后你会发现,计算机原来就是这么个玩意儿~~
计算机简化成一个模型:
在我看来(上面的绝对正确,这一段剩下的内容是我自己的想法,毕竟我没上过大学,呵呵):
就类似于学童时代拿着手指头算加减法,内存就是手指头,脑子就是cpu!
手指头做记录,脑子做计算!
像不像?其实就死计算机的操作太快了而已!
问题就来了,大量运算或者复杂运算的时候,手指头就不够了吧,就要节省着用,这就是要节省内存的原因,接着往下看
什么是“对象”?
生活中:对象是一个个实实在在存在的物体
程序中:类的实例化,一般具有属性和方法
思考一下,对象在内存中被创建的时候到底是个什么东西?
由前面的我们可以知道,说白了,一个确定的对象就是一小块内存加上一种定义(定义怎样的排列方式是一种什么样的信息)而已!下面就是详细剖析:
类中的成员变量为什么可以通过对象名打点的方式找到?
其实对象创建在堆内存中,其实就是在内存中划出一小块内存,来放这个对象!
但是问题又来了,这个内存该划成多大呢?这是jvm头疼的事,但是肯定是有大小的,要不然jvm怎么划分!
再想一下,对象的属性是不是每个对象都不一样?是不是每个人都要标示?但是对象的行为(即类中的方法)是不是每个人都一样?
既然这样,那好,java的设计者们就这样设计了jvm:
我可以把一块有限内存分成几种不同用途的块,提高使用效率!
堆内存,栈内存,方法区,常量池等!
属性每个人都有,我就给每个人所在的内存块中放入表示内存的小块,放在对象所在的内存块,这就是堆内存的由来!放那些程序运行过程中需要被记录住的信息。
类的方法我也要记录,但是每个对象都记录的话就太浪费了,那我就划出来一块地方,专门存方法,这就是方法区喽~~
但是,for循环里面的变量用完之后还有用吗?很明显没用了,局部变量都是这样的,不是吗?
所以有了栈内存,存放那些使用过之后就立刻释放的变量,节省内存!
这么多内存块我怎么找到哪个是哪个呢?于是,内存块就有了地址,编上编号,就知道哪个是什么了!
通过这个编号我们就能找到我们在程序中所定义的对象在内存中的真身啦!!!!!!!!!
累死了,终于知道对象在内存中的表现了。
某个类型对象的大小其实是确定的:万能父类Object(连这都不知道的话,滚去百度)是固定的8K,再加上自身属性所占的大小,就是一个对象在堆内存中所占用的大小了!
这就好办多了,其实所谓的对象名,即所谓的引用,那个引用的值就是对象所在内存块的编号(怎样编号?操作系统的事,这个我就真不知道了,想知道的话,东西太多了,所以有些东西深究不得),
通过这个编号就能找到对象,我们也说成,引用指向那个对象!
什么是匿名对象?就是没有被任何一个引用指向的对象。
但是堆内存中是确确实实存在的,只不过栈内存中没有响应的引用指向它罢了!
自己可以想象到了吧!
但是不起名字也就没法用,会造成一直占用堆内存,会造成浪费啊!怎么办?
这就是javaGC大神干的活了,当堆内存中一块内存没有任何引用指向它的时候,它也就没有存在的必要了,GC大神会在某个不确定的时间(GC大神运行也是很耗费内存的,所以一般不会一直运行)把它回收掉!
敲了好久,不知道能不能帮到你,如果觉得明白了,内心感谢一下俺吧敲一个多小时啊~~
作者:
HM马明宇
时间:
2013-4-11 02:00
{:soso_e140:}我开始敲回复的时候,还没有见有答案呢,等我敲好,楼主都大概明白了~~
作者:
HM马明宇
时间:
2013-4-11 02:01
纯手敲啊~~~
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2