黑马程序员技术交流社区
标题: 字符串 [打印本页]
作者: 郭军亮 时间: 2013-5-16 15:57
标题: 字符串
请帮忙分析一下String s="abc"和String s=new String("abc")在内存中的情况,为什么前者有一个对象,而后者有两个对象呢
作者: ZhaoYuBetter 时间: 2013-5-16 16:06
用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。
String s = "abc"是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",
如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”
作者: 黑马-许鹏 时间: 2013-5-17 03:36
同问,求大神解释
作者: 石贤芝 时间: 2013-5-17 04:01
本帖最后由 石贤芝 于 2013-5-17 04:05 编辑
第一句代码只有一个对象:“abc”,在字符串常量池中(栈里面),变量 s 不是对象,它是指向对字符串对象“abc”的引用,也就是说 s 的值是对象“abc”的内存地址 。
第二句代码里面有两个对象:对象“abc” 和 对象String("abc"),在堆内存中;
第二句代码执行时,虚拟机先会在堆内存中查找有没有 “abc” 对象,如果没有,就要在堆内存中开辟内存空间创建“abc”对象,然后把“abc”作为参数来创建另外一个对象String("abc")。变量 s 是指向对象String("abc") 的引用。这样第二句代码执行后,堆内存中就多了两个对象。
作者: Super_Class 时间: 2013-5-17 16:32
本帖最后由 Super_Class 于 2013-5-17 16:36 编辑
String s1 = "abc"; //创建一个字符串对象在常量池中
String s2 = "abc"; 这里创建的时候,(没有用new,不会在堆内存中),到常量池中找这个对象。 相当于 s2 = s1;
System.out.println(s1.equals(s2)); //true
System.out.println(s1==s2); //true 这里相等时因为常量池中已经有了abc这样一个对象
String s3 = new String ("abc");//在堆内存中创建一个字符串对象
String s4 = new String ("abc");
System.out.println(s2==s3); //false
System.out.println(s3.equals(s4)); //true String类重写了equals方法
System.out.println(s1==s3); //false // 比较的是地址。一个在堆内存,一个在常量池中。肯定不一样
System.out.println(s1.equals(s3)); //true String类重写了equals方法,就变成了比较内容了
作者: 郭军亮 时间: 2013-5-17 22:48
意思是String s=new String("abc")在常量池中建了一个对象,在堆内存中也建了一个对象,是这个意思吧
作者: librazeng 时间: 2013-5-18 00:02
这个问题问得好啊,面试题,很多人都说不清楚!上面的回答都不完全正确!且看终极答案:
1.String s="abc"
String类在内存中管理着一个文字池(pool of literal strings,也称为字符串常量池,是常量池的一部分),池中所有相同的字符串常量被合并,只占用一个空间。
这里创建“abc”时,先看文字池中有没有abc,没有就创建了一个abc字符串对象。
2.String s1 = new String("abc")
这里先在文字池中创建一个abc对象,同上。然后new String()时,将abc对象复制一份到堆heap中,new一次就复制一个,s1就指向堆中的abc。(参考下面的API文档)
可以用代码验证:- String s1=new String("abc");
- String s2=new String("abc");
- s1+="d";
- System.out.println(s1==s2);//false,说明s1和s2指向的是堆内各自的abc(从文字池中abc复制过来的)
- System.out.println(s1);//abcd,说明s1指向abc,不然无法和字符d相连接。
复制代码 参考资料:
JAVA API文档中的解释
public String(String original)
Initializes a newly created String object so that it represents the same sequence of characters as the argument; in other words, the newly created string is a copy of the argument string. Unless an explicit copy of original is needed, use of this constructor is unnecessary since Strings are immutable.
初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。由于 String 是不可变的,所以无需使用此构造方法,除非需要 original 的显式副本。
网络文章
String s = new String("abc");你真的了解吗???
http://wyz191.iteye.com/blog/139171
String s="abc"及String s=new String("abc")详解
http://www.cnblogs.com/heima-jieqi/archive/2012/04/10/2440086.html
内存图解:
-
abc.png
(65.46 KB, 下载次数: 0)
String s=new String("abc");
作者: Sword 时间: 2013-5-21 09:43
如果问题已经解决了,那么大家请把帖子的类型改为“已解决”,谢谢合作
作者: kaka小明 时间: 2013-5-21 10:36
ZhaoYuBetter 发表于 2013-5-16 16:06
用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。
String s = "abc"是先在栈中 ...
“abc”是存在栈中的吗?不是存放在常量池中的吗?求解?
作者: 风云 时间: 2013-5-21 11:54
String("abc") "abc"就是一个对象,后来又new一下就在次穿件乐意对象
作者: 风云 时间: 2013-5-21 11:55
穿件乐意 改为创建 刚写错了
作者: Super_Class 时间: 2013-5-21 15:32
String s = "abc';
先解释一下这个,这个创建对象的时候,是到字符串池中去找“abc”这个对象。(注意,我说“abc”是个对象);
如果找不到,会在字符串池中建一个对象,赋给引用型变量s;
有必要解释一下String s1 = “abc”;
s == s1; 返回结果 是true;
创建s1的时候,也是先到字符串池中找“abc”对象,如果找到了,就直接把这个对象赋给引用型变量s1;
所以 s和s1是相等的;
String s = new String("abc");
new 对象,都是在堆内存中创建,然后构造方法进栈。接着将引用赋给了 变量s,构造方法弹栈;
每一次new ,都会在堆内存中创建一片空间。所以即使是一样的内容,也不相等
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |