黑马程序员技术交流社区

标题: 关于string的内存分布 [打印本页]

作者: 328078121    时间: 2013-8-29 10:25
标题: 关于string的内存分布
本帖最后由 黄兴旺 于 2013-8-29 19:32 编辑

一直搞不懂,string s="afdsfs";
和string s1=new string("fsadfsdf ");
他们存在的内存区域有什么区别,还有他们的消亡时间,最重要的是string s="afdsfs";的消亡时间~~~
作者: 白磊    时间: 2013-8-29 10:54
栈 里面存的你的对象名,属性名,参数名
堆 里面存放的是你new出的对象,栈里的对象名s1指向这个对象,java堆中的对象是由垃圾回收器负责清除长时期不再使用的对象。当对象没有被指向的时候,这个兑取中的对象便会被自动清除了。   至于栈中的对象什么时候清除,我也不是很清楚,希望有高手解答吧
作者: 328078121    时间: 2013-8-29 11:00
白磊 发表于 2013-8-29 10:54
栈 里面存的你的对象名,属性名,参数名
堆 里面存放的是你new出的对象,栈里的对象名s1指向这个对象,java ...

貌似,string s="dsfsdf";   "dsfsdf";这个数据在哪里存放? 貌似不在堆里吧~~,好像在方法区 ~他的消亡时间~~·?

作者: 月黑风高    时间: 2013-8-29 11:07
在字符串建立时,在内存中有一个字符串缓冲区,或者叫做字符串常量池。在创建新的字符串时,就会到内存中的字符串常量池中查找,没有才创建。;有的话就直接用,所以比较s和s1的地址值是一样的。

解析:
String s="abc";
在字符串常量池中创建了一个abc字符串,并把地址赋值给了s引用型变量。
在内存中只产生一个对象。
String s1=new String("abc");
在堆内存中创建了一个String类型的对象,此对象在构造的时候接受了一个字符串对象“abc”,但并没有涉及到字符串常量池中的任何动作。
在内存中产生两个对象,new了一个,接收了一个。

区别:
前者是在常量池中创建一个对象;后者是在堆内存中创建两个对象。
常量池中装的都是字符串对象。
比较对象是否相同,用equals方法,打印输出结果为true
当年在查看equals源码的时候,实际上比较也是地址值,怎么是这样呢?

原因:
String类是Object类的子类,在使用时,String类将equals方法进行了复写。
建立了字符串对象根据自身特点比较是否相同的依据,比较的是内容。


作者: 白磊    时间: 2013-8-29 11:09
328078121 发表于 2013-8-29 11:00
貌似,string s="dsfsdf";   "dsfsdf";这个数据在哪里存放? 貌似不在堆里吧~~,好像在方法区 ~他的消亡 ...

这种方法:string s="dsfsdf";  这个 "dsfsdf“是从对象池中取出来的。应该算尺常量区的吧。

作者: 行如止水    时间: 2013-8-29 14:09
板凳说的没错,但是有些地方没有解释清楚。
首先,在程序中出现的所有字符串都会出现在字符串常量池中,但注意的是,字符串常量池中不会存储相同的字符串。
也就是说:
String str1 = "hello";
String str2 = "hello";
这两个String对象的指针是一样的。而”hello“在内存中只存在一个。

再来说:   String str = new String("hello");
首先,由于字符串“hello”的存在,所以在字符串常量池中会出现一个“hello”;
然后这句话又调用了String类的构造函数,这样会在栈中出现一个“hello",
然后str指向它。
分析一下这样个问题:
String str1 = "hello";
String str2 = new String("hello");
问str1 == str2的结果,,,结果是false;
作者: 328078121    时间: 2013-8-29 14:15
月黑风高 发表于 2013-8-29 11:07
在字符串建立时,在内存中有一个字符串缓冲区,或者叫做字符串常量池。在创建新的字符串时,就会到内存中的 ...

谢谢,很详细~~~
作者: 328078121    时间: 2013-8-29 14:21
行如止水 发表于 2013-8-29 14:09
板凳说的没错,但是有些地方没有解释清楚。
首先,在程序中出现的所有字符串都会出现在字符串常量池中,但 ...

然后这句话又调用了String类的构造函数,这样会在中出现一个“hello",
字符串都在常量池中,在堆中就出现不了?
我觉得是string s=new string("abc");时这个“abc”是在常量池中,但是构造时在堆中创建一个对象,这个对象里封装的是常量池中“abc”的地址?是不是这样?

作者: 行如止水    时间: 2013-8-29 15:05
328078121 发表于 2013-8-29 14:21
然后这句话又调用了String类的构造函数,这样会在栈中出现一个“hello",
字符串都在常量池中,在堆中就出 ...

刚才是我打错了,是在堆中。
字符串在常量池中也可能会在堆中创建。
这个String s = new String("abc");
“abc”在常量池中会存在,然后由于调用了new 关键字和String的构造函数,
所以会在堆中存在一个字符串“abc”然后让s指向它。


作者: 泡沫之夏    时间: 2013-8-30 01:02
String s = "afdsfs";是在常量池中,String s1=new String("fsadfsdf");其实创建了两个对象,但是s1指向堆内存




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