A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 黑马-李勇 中级黑马   /  2012-5-22 15:30  /  1746 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

String s1="abc";
String s2=new String("abc");

s1和s2有什么区别?
s1在内存中有一个对象。---->这个我明白
s2在内存中有两个对象。---->这个我想不通,有谁能给解释下吗?

评分

参与人数 1技术分 +1 收起 理由
攻城狮 + 1 赞一个!

查看全部评分

8 个回复

倒序浏览
在栈内存中放了两个String类型的s1和s2,s1指向方法区中的"abc",s2指向堆内存中的“abc”.
回复 使用道具 举报
String s1="abc"; 具体编译过程:
在栈中完成,1>先定义一个名为s1的对String类的对象引用变量:String   s1; 2>在栈中查找有没有存放值为 "abc "的地址,如果没有,则开辟一个存放字面值为 "abc "的地址,接着创建一个新的String类的对象o,并将o 的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为 "abc "的地址,则查找对象o,并返回o的地址。3>将str指向对象o的地址。
String s2=new String("abc"):s2 存储在栈中,原理同上。其值存在堆内存中。用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。
和创建新的类对象时内存分配原理是一样的。
其实这个例子很好的反映了java的内存机制,栈内存中的数据共享性高,运行速度快。在堆内存中存储数据具有更好的灵活性。
回复 使用道具 举报
1. String str=new String("abc")和String str="abc"的字符串“abc”都是存放在堆中,而不是存在
栈中。
2. 其实在在java中有一个“字符数据池”的内存管理机制。
3. String str="abc",执行这句话时,会先去“字符数据池”搜索时候有“abc”这个字符串,如果有
,则将字符串的首地址赋值给str,如果没有,生成一个新的字符串“abc”并且将首地址赋值给str;
4. String str=new String("abc"),执行这句话时,不会考虑时候已经存在了“abc”这个字符串,而
是直接生成一个新的字符串“abc”并将首地址赋值给str,注意“abc”并不放在“字符数据池”中;
5. 由以上分析可知,String str="abc"和效率要高于String str=new String("abc"),因为如果有重复
的字符串时,第一种方式可以节省空间。
6. 下面举例说明一下,好好看看结果,仔细分析原因,上面已经说明的很清楚了:
public class Test{
public static void main(String args[]){
  String s1=new String("abc");//直接在堆中生成新的“abc”
  String s2=new String("abc");//直接在堆中生成新的“abc”
  String s3="abc";//先去“字符数据池”搜索时候有“abc”这个字符串,如果有,则
将字符串的首地址赋值给s3,如果没有,则在“字符数据池”中生成一个新的字符串“abc”并且将首地
址赋值给s3;
  String s4="abc";//去“字符数据池”搜索时发现了上一步生成的“abc”这个字符串
,把该字符串首地址赋值给s4,这时其实s3和s4指向同一个字符数据池中的“abc”
  System.out.println(s1==s2);
  System.out.println(s1==s3);
  System.out.println(s2==s3);
  System.out.println(s3==s4);
}
}
结果:
false
fasle
false
true

评分

参与人数 1技术分 +1 收起 理由
攻城狮 + 1 赞一个!

查看全部评分

回复 使用道具 举报
String s1="abc";
String s2=new String("abc");

s1和s2有什么区别?
s2在内存中有两个对象。---->先给你一个API官方的解释:String(String original)
                                                                             初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。
-------------------------------------->然后我说下我的理解:String s2=new String("abc");是由两部分组成:第一部分("abc");“abc"已经是一个对象,new 又是一个对象,就是两个对象了,同时(NEW的对象是"abc"对象的副本,但也是独立对象),同时赋值给一个变量S2.
----------------------------------------也就是S2这个变量同时指针指向了2个对象。一个"abc",一个由new产生的"abc"副本。

评分

参与人数 1技术分 +1 收起 理由
攻城狮 + 1 赞一个!

查看全部评分

回复 使用道具 举报
String s1="abc";
先在堆中创建一个引用S1,然后在常量池中找有没有abc,没有就在常量池创建。
String s2=new String("abc");是先创建一个应用S2,然后在堆中开辟一段空间,里面放了abc
一个对象是堆中开辟的空间,一个对象是常量池中的abc


回复 使用道具 举报
以下是我的理解,有不足之处请指正
String s1="abc";
String s2=new String("abc");
String s3="abc";
System.out.println(s1==s2);//false
System.out.println(s1==s3);//true
当执行String s1="abc"时,内存方法区的常量池中就存在了“abc”字符串,引用s1指向它,之后String s3="abc"会先到常量池中查找是否有“abc”字符串存在,如果有,那么内存中就不会再开辟空间以免资源的浪费,而是将s3指向已存在的字符串,而String s2=new String("abc")是在堆内存中new一个String对象,同时初始化使用了常量池中的“abc”字符串对象,所以有两个对象。
回复 使用道具 举报
谢谢各位,可能abc是一个对象,new是另一个对象,这种理解可能更能让我懂吧。
回复 使用道具 举报
攻城狮 黑马帝 2012-5-22 17:36:16
9#
每一个字符串都是String实例后的对象
所以“abc”是一个对象··
new关键字会在堆内存中生成一个对象 例如new person();
所以你new了一个 然后“abc”又是一个 所以就是两个
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马