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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王红潮 中级黑马   /  2012-9-7 00:52  /  2050 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 王红潮 于 2012-9-7 13:51 编辑

class Test5
{
public static void main(String[] args)
{
  String s1 = "你好Java";
  String s2 = "你好" + "Java";
   System.out.println("s1==s2 : " + (s1 == s2));
  String s3 = "你好";
  String s4 = "Java";
  String s34 = s3 + s4;
  System.out.println("s34=" + s34);
  System.out.println("s34==s1 : " + (s34 == s1));// 这里返回false
  final String s5 = "你好";
  final String s6 = "Java";
  String s56 = s5 + s6;
  System.out.println("s56=" + s56);
  System.out.println("s56==s1 : " + (s56 == s1));//这里返回 true
}
}

为什么加了final之后的字符串连接运算就返回true了,如果字符串对象想要进入常量池,不得调用intern()方法才能入池吗,这里加了final修饰之后的运算结果与s1是相等的,求解!

点评

这个问题是论坛的高频问题之一,建议你平时多看论坛别人如何解决问题的  发表于 2012-9-7 08:23

评分

参与人数 1黑马币 +10 收起 理由
刘芮铭 + 10 鼓励一下

查看全部评分

5 个回复

倒序浏览
本帖最后由 魏-玉-彪 于 2012-9-7 07:46 编辑

class Test5
{
public static void main(String[] args)
{
  String s1 = "你好Java";
  String s2 = "你好" + "Java";
   System.out.println("s1==s2 : " + (s1 == s2));
  String s3 = "你好";
  String s4 = "Java";
  String s34 = s3 + s4;
  System.out.println("s34=" + s34);
  System.out.println("s34==s1 : " + (s34 == s1));// 这里返回false
  final String s5 = "你好";
  final String s6 = "Java";
  String s56 = s5 + s6; //这里的结果是  s56=“你好Java”
  System.out.println("s56=" + s56);
  System.out.println("s56==s1 : " + (s56 == s1));//这时 s1="你好Java" 在内存中和 s56是一个内容。String s56 是字符串类型变量,不是常量,常量的值运算可以赋值给变量,所以 s56 与常量无关
}
}
回复 使用道具 举报
java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。“==”比较的是两个变量的值是否相等,对于引用表示两个变量在堆中存储的地址值是否相同及栈中内容是否相同,而equals比较的是两个对象是否对同一对象的引用,即堆中的内容是否相等。String s2 = "你好" + "Java";已经另外创建新的对象,s2指向它,System.out.println("s1==s2 : " + (s1 == s2)); 是false。为什么加final后结为true呢?是因为定义final后就表示两个变量的地址值不允许改变,他们连接以后就变成“你好java”,而这个字符串对java字符串池值已经存在,所以s1也就指向它了。
回复 使用道具 举报
final修饰的变量即为常量,s5和s6是常量,此时s56=s5+s6,就等于s56=“你好"+"java",先在字符串缓冲池内查找是否有"你好java ",s1地址指向的是"你好java",这样缓冲池就不会再创建"你好java"了,s56指向s1指向的"你好java",所以s56==s1就会true。是否能明白呢?
回复 使用道具 举报
当执行到 String s34 = s3 + s4; 的时候,jvm会创建一个StringBulider对象,然后用append()方法把s3和s4连接起来,然后调用StringBulider的toString()方法,它会在堆内存中创建一个String对象,然后赋给s34,而s1是指向字符串常量池中的"你好Java"对象,所以用“==”比较的是它们两个引用的地址值,当然就返回false;

下面的问题据我个人的理解:当用final修饰以后,s5和s6会强制指向字符串常量池中的对象,用“+”操作的时候和s2的操作方式是相同的,两者都是指向字符串常量池中的对象,而且它们的内容相同,所以就指向了同一个地址空间,所以就返回true。我不是很确定,自己的理解,不知道是不是正确,希望强人指出
回复 使用道具 举报
本帖最后由 翁发达 于 2012-9-7 22:58 编辑

这个问题要搞清楚,只有一点,画个图,越画你越明白,有个要点要注意,字符串是一个特殊的类,如果new 则和普通类一样,在堆内存创建对象,如果是直接赋值,那么在字符串区,
请看下图:
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马