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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© linjl_ll 中级黑马   /  2013-11-14 11:38  /  1114 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 linjl_ll 于 2013-11-14 13:14 编辑

我们知道java中字符串是不可变对象,且字符串是很常用的所以自字符串池中缓存了一些字符串,其目的是为了提高性能。但是下面代码我有一些不理解
String a = "a";
String a1 = a+"b";
String a2 = "a"+"b";
system.out.println(a2=="ab")//true
a1=="ab"//false
a1=a+"b"的时候不是在字符池中找是否有“ab”字符串对象,有的话直接将地址给a1啊?
a2="a"+"b"是等于  a2="ab"的,a2也是指向字符池中的“ab”字符串对象的啊!那为什么a1和a2不相等呢?难道在字符池中有2个“ab”??这个不合理啊?

5 个回复

倒序浏览
已下是个人的想法,仅供参考。

String a1 = a+"b";   此时a1的字符串结果是 "ab"  但是内存地址并不是和下面的"ab"地址一致
可能是因为A1构成和下面有些区别。

String a2 = "a"+"b";  这句话的时候  a2="ab";

等待楼下更清晰的答案。。



回复 使用道具 举报
String对象和字符串连接池:       引号内包含文本是String类特有创建对象的方式.为什么呢?因为在JVM内,存在字符串池,其中保存着很多 String对象,并且可以被共享使用,因此它提高了效率.字符串池由String类维护,我们可以调用intern()方法来访问字符串池。当运用引号内包含文本创建对象时,所创建的对象是加入到字符串池里面的.如果要创建下一个字符串对象,JVM首先会到字符串池中寻找,是否存在对应的字符串对象,如果存在,则返回一个己存在对象的对象的引用给要创建的对象引用.如果不存在,才会创建一个新的对象,并返回一个新对象的对象引用给要创建的对象引用.以上这段话理解起来可能比较拗口.用代码理解就是str2和str1是两个对象引用,并指向了同一个对象.所以'=='返回的是true.
       只有引号内包含文本创建对象才会将创建的对象放入到字符串池。String str = new String("abc")这种方法创建的字符串对象是不放入到字符串池的。所以,引号内包含文本创建对象的性能要比后来那种方法创建字符串对象的性能要好。
String str1 = "abc";
String str2 = "abc";

String str3 = str1+str2;   //这种创建方式是不放入字符串池的.
String str4 = str1+"cd";   //这种创建方式是不放入字符串池的.
String str5 = "ab"+str2;   //这种创建方式是不放入字符串池的.

String str6 = "ab"+"cd"; //这种创建方式是放入字符串池的.这种情况实际上是创建了1个对象,abcd"1个对象
String str7 = "abcd";
System.out.println(str1==str2); //返回ture
System.out.println(str6==str7); //返回ture

System.out.println(str4==str6);//返回false     
回复 使用道具 举报
String对象和字符串连接池:       引号内包含文本是String类特有创建对象的方式.为什么呢?因为在JVM内,存在字符串池,其中保存着很多 String对象,并且可以被共享使用,因此它提高了效率.字符串池由String类维护,我们可以调用intern()方法来访问字符串池。当运用引号内包含文本创建对象时,所创建的对象是加入到字符串池里面的.如果要创建下一个字符串对象,JVM首先会到字符串池中寻找,是否存在对应的字符串对象,如果存在,则返回一个己存在对象的对象的引用给要创建的对象引用.如果不存在,才会创建一个新的对象,并返回一个新对象的对象引用给要创建的对象引用.以上这段话理解起来可能比较拗口.用代码理解就是str2和str1是两个对象引用,并指向了同一个对象.所以'=='返回的是true.
       只有引号内包含文本创建对象才会将创建的对象放入到字符串池。String str = new String("abc")这种方法创建的字符串对象是不放入到字符串池的。所以,引号内包含文本创建对象的性能要比后来那种方法创建字符串对象的性能要好。
String str1 = "abc";
String str2 = "abc";

String str3 = str1+str2;   //这种创建方式是不放入字符串池的.
String str4 = str1+"cd";   //这种创建方式是不放入字符串池的.
String str5 = "ab"+str2;   //这种创建方式是不放入字符串池的.

String str6 = "ab"+"cd"; //这种创建方式是放入字符串池的.这种情况实际上是创建了1个对象,abcd"1个对象
String str7 = "abcd";
System.out.println(str1==str2); //返回ture
System.out.println(str6==str7); //返回ture

System.out.println(str4==str6);//返回false     
回复 使用道具 举报
本帖最后由 不抛弃不放弃 于 2013-11-14 13:02 编辑

我怎么发了两遍  
回复 使用道具 举报
a2 = “ab”;
是因为JVM虚拟机有个常量优化机制
当“a”+“b”  每个都是常量的时候,它在编译时就已经将“a”“b”变成一个字符串了“ab”
运行的时候一比较  其实就是“ab”与“ab”在比较  所以是ture
String a1 =a +“b”;
1.首先  “b”是一个常量  而a是一个变量, 当一个变量和一个常量相连接的时候是不可能常量优化的
2.而且字符串串联是通过 StringBuilder(或 StringBuffer)类及其 append 方法实现的。
也就是说a2是没问题的在常量池创建出来,但a1 = a +“b”  a 与字符串“b”相连接的时候,实际上是调用了append方法,就是在堆内存又创建了一个对象,所以a1这个对象和a2这个常量池里的引用是不相等的
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马