黑马程序员技术交流社区

标题: 字符串String对象的改变问题 [打印本页]

作者: 依然超级赛亚人    时间: 2014-7-19 16:38
标题: 字符串String对象的改变问题
本帖最后由 依然超级赛亚人 于 2014-7-19 16:41 编辑

我们知道,字符串一旦定义就不能再改变,比如以下这几句代码:
String s1="hello";
s1="world";
System.out.println(s1);
打印结果为world.

我们知道,虽然变量s1的结果改变了,但这只不过是它指向了不同的地址(从指向hello变为了指向world)而已,而hello仍然在内存中,没有被改变。不过我想知道到的是我们如果想使用hello这个字符串该怎么操作呢?是在定义一个新变量去引用吗?也就是:String s2="hello";如果是在这样操作,那是又在内存中存了另外一个hello.还是把原来的hello地址赋给了s2?


>>>我估计这个问题对于大家来说可能很简单,但我确实想不起它的原理是上面说的哪一种,或者两种都不对,我也没找到之前的记录,所以还烦请各位给予指导。

作者: icris    时间: 2014-7-19 18:05
String s2 = "hello"; 是把原来的hello地址赋给了s2
String s2 = new String("hello"); 是又在内存中存了另外一个hello
作者: fantacyleo    时间: 2014-7-19 18:10
String s1="hello";这句之后,"hello"会被存到常量池中。String s2="hello";会让s2指向常量池中的"hello",而不会再创建对象。
作者: icris    时间: 2014-7-19 18:10
  1. String s1 = "h";
  2. String s2 = "h";
  3. String s3 = new String("h");
  4. String s4 = new String();
  5. s4 = "h";
  6. System.out.println(s1==s2); // true
  7. System.out.println(s1==s3); // false
  8. System.out.println(s1==s4); // true
复制代码

补充测试
作者: java—family    时间: 2014-7-19 18:48
1.java运行环境有一个字符串池,由String类维护,执行语句String str="abc"时:                                                                                                                                         1.首先查看字符串池中是否存在字符串"abc",如果存在则直接将“abc”赋给str,如果不存在则先在  字 符串池中新建一个字符串"abc",然后再将其赋给str.  2.执行语句String str = new String("abc");时。不管字符串池中是否存在字符串“abc”,直接新建一个字符串“abc”,(注意,新建的字符串“abc”不是在字符串池中),然后将其赋给str  。
作者: java—family    时间: 2014-7-19 18:59
补充哈,String str = new String("abc");  如果常量池中有adc  是拷贝过去的。常量池中不会存放相同的字符串
作者: as_heima    时间: 2014-7-19 19:27
String是一个特殊的包装类数据。可以用:
String str = new String("abc");
String str = "abc";
两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。
而第二种是先在栈中创建一个对 String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。
作者: 依然超级赛亚人    时间: 2014-7-19 22:07
icris 发表于 2014-7-19 18:05
String s2 = "hello"; 是把原来的hello地址赋给了s2
String s2 = new String("hello"); 是又在内存中存了另 ...

恩啊,知道了,hello放在常量池,s2指向它的时候,它就把自己的地址赋给它了。
作者: 依然超级赛亚人    时间: 2014-7-19 22:08
fantacyleo 发表于 2014-7-19 18:10
String s1="hello";这句之后,"hello"会被存到常量池中。String s2="hello";会让s2指向常量池中的"hello", ...

OK,终于知道了它的原理。:handshake
作者: 依然超级赛亚人    时间: 2014-7-19 22:10
icris 发表于 2014-7-19 18:10
补充测试

呃...我有点迟钝,这个程序的目的在于表达....?请明示。
作者: 依然超级赛亚人    时间: 2014-7-19 22:14
java—family 发表于 2014-7-19 18:48
1.java运行环境有一个字符串池,由String类维护,执行语句String str="abc"时:                           ...

String str =new String("abc");中创建的这个新串不在常量池?在哪里呢?堆中吗?而且它新生成"abc"不浪费内存空间吗?
作者: 依然超级赛亚人    时间: 2014-7-19 22:16
java—family 发表于 2014-7-19 18:59
补充哈,String str = new String("abc");  如果常量池中有adc  是拷贝过去的。常量池中不会存放相同的字符 ...

意思是说没有创造新的"abc"串吗?还是用的原来常量池中已经存在的旧串?
作者: 依然超级赛亚人    时间: 2014-7-19 22:20
as_heima 发表于 2014-7-19 19:27
String是一个特殊的包装类数据。可以用:
String str = new String("abc");
String str = "abc";

嗯....恕我不敢苟同您的意见,经过前面的一些回答,我也想起了一些东西,也感觉这以上这两种形式的创建方式都不会在栈或堆中创建对象,它们应该在常量池中创建"abc",不知您是否赞同这个说法?
作者: icris    时间: 2014-7-19 22:46
依然超级赛亚人 发表于 2014-7-19 22:10
呃...我有点迟钝,这个程序的目的在于表达....?请明示。

以 s1 的地址做比较基准
s2 是直接引用 s1 的地址(s1 == s2),
s3 是新建另一个 "h"(s1 != s3),
s4 跟 s2 效果相同(至少赋值效果相同)(s1 == s4)
作者: java—family    时间: 2014-7-20 00:30
依然超级赛亚人 发表于 2014-7-19 22:14
String str =new String("abc");中创建的这个新串不在常量池?在哪里呢?堆中吗?而且它新生成"abc"不浪 ...

这个abc在堆中   因为他用了new所以必须开辟空间。堆中有垃圾回收机制  ,
作者: as_heima    时间: 2014-7-20 09:16
依然超级赛亚人 发表于 2014-7-19 22:20
嗯....恕我不敢苟同您的意见,经过前面的一些回答,我也想起了一些东西,也感觉这以上这两种形式的创建方 ...

当然同意~不过常量池貌似也在栈中吧:)
作者: as_heima    时间: 2014-7-20 09:30
依然超级赛亚人 发表于 2014-7-19 22:14
String str =new String("abc");中创建的这个新串不在常量池?在哪里呢?堆中吗?而且它新生成"abc"不浪 ...

String str =new String("abc");按我目前学习到的,这个是在堆中开辟个空间,然后去常量池里找有没有"abc",如果有,在堆中开辟的空间将存储常量池的地址;如果没有就在堆中存储"abc"~仅供参考:)
作者: meibinlove    时间: 2014-7-20 09:40
存了另一个HELLO
作者: 導ぷ仙″兲蕐    时间: 2014-7-20 13:05
把原来的hello地址赋给了s2
作者: 依然超级赛亚人    时间: 2014-7-20 22:40
導ぷ仙″兲蕐 发表于 2014-7-20 13:05
把原来的hello地址赋给了s2

已经了然,多谢!
作者: 依然超级赛亚人    时间: 2014-7-20 22:54
as_heima 发表于 2014-7-20 09:30
String str =new String("abc");按我目前学习到的,这个是在堆中开辟个空间,然后去常量池里找有没有"abc ...

常量池中没有的话就在堆中存储吗?总是感觉有些不对劲。还有,您说常量池也在栈中?恕我有所怀疑,当时老师好像没有这样讲过(常量池好像在方法区),您能给一些具有说服性的参考资料吗?
作者: DSY    时间: 2014-7-20 23:19
依然超级赛亚人 发表于 2014-7-19 22:20
嗯....恕我不敢苟同您的意见,经过前面的一些回答,我也想起了一些东西,也感觉这以上这两种形式的创建方 ...

使用String a =new String("abc")会在栈区或者堆区创建一个新的字符常量,而第二句如果常量池中存在"abc"则不创建,否则就在常量池中创建一个“abc”,就是 使用new 一定会新建个对象
作者: as_heima    时间: 2014-7-21 10:40
依然超级赛亚人 发表于 2014-7-20 22:54
常量池中没有的话就在堆中存储吗?总是感觉有些不对劲。还有,您说常量池也在栈中?恕我有所怀疑,当时老 ...

http://zhidao.baidu.com/link?url=bUnvBfAva7feguKld-m0EUM3TVCaa48HnxOfqzVnG-DOtoTIeF3LGwNib91S_UQwBDlGbi4Vdku_7Wql0-TyQa
也不知道这个算不算、您瞧瞧吧~:)




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