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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 白倩 黑马帝   /  2011-10-28 15:24  /  3519 人查看  /  10 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

public class TestStr {
        public static void main(String[] args){
                String s1 = "Love";
        String s2 = "Lo"+"ve";
        String s3 = "Lo";
        String s4 = "ve";
        String s5 = s3 + s4;
        System.out.println(s1==s2);
        System.out.println(s1==s5);
        System.out.println(s1.equals(s5));

                }
               
        }
运行的结果:
true
false
true
运行的结果让我很疑惑,只知道==是比较值,equals是比较对象的引用。高手帮忙分析一下!

评分

参与人数 2技术分 +2 收起 理由
杨玉揆 + 1
宁超 + 1

查看全部评分

10 个回复

倒序浏览
你加句话就明白了、
        System.out.println( s1.hashCode());
        System.out.println( s2.hashCode());
        System.out.println( s3.hashCode());
        System.out.println( s4.hashCode());
        System.out.println( s5.hashCode());

评分

参与人数 1技术分 +1 收起 理由
宁超 + 1

查看全部评分

回复 使用道具 举报
Simple 发表于 2011-10-28 15:43
你加句话就明白了、
        System.out.println( s1.hashCode());
        System.out.println( s2.hashC ...

1,2,5的哈希值都一样的哦~
回复 使用道具 举报
黄健 黑马帝 2011-10-28 16:53:07
板凳
迷惑是在这里System.out.println(s1==s5);// 返回false
因为s5又是一个新的对象,当连接字符串时,只要有一个不是字符串常量("abc"这种称为字符串常量),那么连接后就直接在堆内存中创建一个新的对象,而不去String池中查找。
而使用常量字符串进行连接时,如"Lo"+"ve",它会拿连接后的字符串在 String池中找是否已经存在,如果存在则不再创建新的字符串,而是返回已存在的字符串的引用;如果不存在则在String池中创建一个字符串,然后返回它的引用。

评分

参与人数 1技术分 +1 收起 理由
宁超 + 1

查看全部评分

回复 使用道具 举报
白倩 黑马帝 2011-10-28 17:15:56
报纸
Simple 发表于 2011-10-28 15:43
你加句话就明白了、
        System.out.println( s1.hashCode());
        System.out.println( s2.hashC ...

明白了!
回复 使用道具 举报
绿影 黑马帝 2011-10-28 20:31:38
地板
我却看迷糊了。s1和s5的hashcode一样,可以理解。==比的是两个引用的地址,s1和s2的地址都是一样,s1和s5的地址为何不一样了呢?
回复 使用道具 举报
李建雄 黑马帝 2011-10-28 20:48:51
7#
本帖最后由 李建雄 于 2011-10-28 20:58 编辑

public class TestStr {
        public static void main(String[] args){
                String s1 = "Love";
        String s2 = "Lo"+"ve";
        String s3 = "Lo";
        String s4 = "ve";
        String s5 = s3 + s4;
        System.out.println(s1==s2);
        System.out.println(s1==s5);
        System.out.println(s1.equals(s5));

                }
               
        }
运行的结果:
true
false
true
运行的结果让我很疑惑,只知道==是比较值,equals是比较对象的引用。高手帮忙分析一下!

------------------------------------------
返了,==是比较地址,
equals比较值
上面的结果中,s1与s2是指向同一个"Love"  因此第一句true
第二句为false不好理解,可能是s5中存的一个运算规则
第三名,equals比较值,true

评分

参与人数 1技术分 +1 收起 理由
宁超 + 1

查看全部评分

回复 使用道具 举报
咖啡 黑马帝 2011-10-29 22:51:39
8#
==比较值是否相等,equals比较对用对象是否相同,  System.out.println(s1==s5);
        System.out.println(s1.equals(s5));因为它的HahCode值不相等,所以...

回复 使用道具 举报
o火o把o 黑马帝 2011-10-30 00:05:50
9#
终于找到我个人认为的可以解释地通小白童鞋的这个问题的证明方法了,哎!困扰我很久了~

代码:
  1.             String s1 = "Love";
  2.         String s3 = "Lo";
  3.         String s4 = "ve";
  4.         String s5 = s3 + s4;
  5.         
  6.         System.out.println("hashcode s1:"+s1.hashCode());
  7.         System.out.println("hashcode s5:"+s5.hashCode());
  8.         System.out.println("memory address hashcode s1:"+System.identityHashCode(s1));
  9.         System.out.println("memory address hashcode s5:"+System.identityHashCode(s5));
复制代码
运行结果:

hashcode s1:2374546
hashcode s5:2374546
memory address hashcode s1:12677476
memory address hashcode s5:33263331

看来== 的判断判断结果和内存的实际地址相关,而这个实际地址由 System.identityHashCode 可以窥见一斑.

而对于API中对此方法的描述:"返回给定对象的哈希码,该代码与默认的方法 hashCode() 返回的代码一样,无论给定对象的类是否重写 hashCode()。null 引用的哈希码为 0",还有些不解,期待大师解答~



评分

参与人数 1技术分 +1 收起 理由
宁超 + 1

查看全部评分

回复 使用道具 举报
贺洪京 黑马帝 2011-10-30 10:18:25
10#
这个问题很经典,public class TestStr {
        public static void main(String[] args){
                String s1 = "Love";
        String s2 = "Lo"+"ve";
        String s3 = "Lo";
        String s4 = "ve";
        String s5 = s3 + s4;
        System.out.println(s1==s2);
        System.out.println(s1==s5);
        System.out.println(s1.equals(s5));

                }
               
        }
当你第一次定义S1的时候在堆内存就给你new出了一个内存空间来放置“love”S1在栈内存中来指向它,当你定义S2并为其赋值的时候在String类内部和堆内存的实现机制是这样的:其实String类的字符窜存储机制是以字符数组在内部存储的,它首先会在字符数组中放置LO这两个字符,当它遇到字符连接号+之后就会又出新new一个字符数组先吧原来的LO放进去再追加后面的VE,所以当完成字符串追加后它就会在堆内存中查找看看是否有与之相匹配的字符串,如果有的话堆内存中就不在为他开启新的内存空间了,而是拿S1所对应的堆内存空间。所以S1、S2它们其实指向的是一个堆内存地址。后来你又定义并赋值了S3、S4,这是堆内存会出新分出两块内存,然后你又定义并赋值了S5=S3+S4这是堆内存中已经有了S3和S4相对应的内存空间,所以它们里边的内容相连的话就会合并到一个新的内存空间里去,所以S5和S1、S2指向的堆内存空间是不同的.你有==来比较的话比较的是堆内存的地址,而你用eques来比较的话就是比较堆内存空间里的内容显然,它们里边的内容都是一样的,所以相等

评分

参与人数 1技术分 +1 收起 理由
宁超 + 1

查看全部评分

回复 使用道具 举报
==是比较地址和值;
而equals比较的只是值;
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马