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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 陈钦涛 中级黑马   /  2013-10-3 11:47  /  1141 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 陈钦涛 于 2013-10-3 15:25 编辑

在JAVA中除了8种基本类型之外,其他的都是类对象及其引用。所以 "XYZ"在JAVA中是一个String对象,对于String类对象来说它的对象值是不能修改的,也就是具有不变性。
但是在下面程序中:
  1. public class TestString {
  2. public static void main(String args[]) {
  3. String s = "Hello";
  4. s = "Java";
  5. String s1 = "Java";
  6. String s2 = new String("Java");
  7. System.out.println(s);
  8. System.out.println(s == s1);
  9. System.out.println(s == s2);
  10. }
  11. }
  12. /*output:
  13. *Java
  14. *true
  15. *false
  16. */
复制代码
打印出s的结果是"Java",看起来s所引用的String变量好像是被修改了,但是如果你了解JVM(Java虚拟机)处理String变量时的机制,你就会知道事实并非如此。


在JVM的工作过程中,会创建一片的内存空间专门存入String对象,我们把这片内存空间叫做String池。
对于语句String s= "Hello";,当JVM看到"Hello"时,会在String池创建String对象存储它,并将它的引用返回给String变量s。
语句s = "Java";,当JVM看到"Java"时,会在String池创建新的String对象存储它,再把新建的String对象的引用返回给String变量s。而原先的String对象"Hello"仍然在String池内,并没有消失,它是不能被修改的。
所以我们仅仅是改变了变量s的引用,而没有改变它所引用的对象,因为String对象的值是不能被修改的。  

String s1 = "Java";,JVM首先在String池里面看能否找到字符串"Java",如果找到则返回它的引用给s1,否则创建新的String对象,放到String池里。这里由于有s = "Java",所以对象已经被引用,所以依据规则s和s1都是引用同一个对象。所以s==s1返回true。(注: 比较运算符==,对于非基本类型,是比较两引用是否引用内存中的同一个对象)。

String s2 = new String( "Java");,JVM首先还是在String池里面看能否找到字符串 "Java",如果找到,不做任何事情;否则创建新的String对象,放到String池里面。由于遇到了new关键字,还会在内存上(不是String池里面)创建String对象存储 "Java",并将内存上的(不是String池里面的)String对象返回给s2。所以s==s2将返回false,因为它们引用的不是同一个对象。

所以对于语句String s = new String("XYZ") + new String("XYZ");
JVM先在String池中创建一个String对象存储"XYZ",然后由于遇到new关键字,再在内存上创建一个String对象存储"XYZ";  
接着由于String池中已经有了"XYZ"的对象,所以第二个new语句不会在String池中创建对象,而只会在内存上创建一个String对象;  

最后两个字符串相加会在String池中创建一个String对象"XYZXYZ",并将其引用传给s。  
所以总共会创建4个String对象。

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

2 个回复

倒序浏览
哥们,看着你这篇文章真是难受,不过文意勉强看懂了,代码一定要规范啊,不然阅读起来难受的要命,你说的内存上,哥们你说的是堆还是栈?请指明行么?

评分

参与人数 1黑马币 +3 收起 理由
乔兵 + 3

查看全部评分

回复 使用道具 举报
本帖最后由 陈钦涛 于 2013-10-3 15:45 编辑
Nocturne 发表于 2013-10-3 15:14
哥们,看着你这篇文章真是难受,不过文意勉强看懂了,代码一定要规范啊,不然阅读起来难受的要命,你说的内存上, ...

谢谢你的提醒哈,我重排了,然后我看了我贴出来的其他文章还好它们不会出现格式混乱的问题。
上面提到的内存区域除了有写明是String池(常量池),就是指堆内存的,然后栈内存的变量储存对堆内存的对象或常量池中字符串的引用地址。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马