2个String对象到底是怎么判断是否 == 的?String s3 = "fff";
String s4 = "fff";
System.out.println(s3 == s4);
这个结果是true,我的理解是这种写法在栈空间里s3和s4其实都是指向堆空间里的“fff”,所以s3就是等于s4的,比较的是他们栈空间的编码,所以相等但是
String s = new String("fff");
String s2 = new String("fff");
System.out.println(s == s2);这样写的话结果就是false,相当于这二个引用虽然都是“fff”,但是指向的其实是堆空间里的2块内存,所以就造成了他们不==,但是我又不理解在这里比较的是什么值?因为我打印以上s1,s2,s3,s4的hashCode,发现都是一样的“101286”看了下api文档,String重写了hashCode()方法
返回此字符串的哈希码。String 对象的哈希码按下列公式计算:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
使用 int 算法,这里 s[i] 是字符串的第 i 个字符,n 是字符串的长度,^ 表示求幂。(空字符串的哈希码为 0。) 那既然所有的“fff”都是一样的hash码,为什么通过new的方式就不等?直接写的方式就等呢?其实也不是什么大的问题,就是搞不明白,有点纠结
String s4 = "fff";
System.out.println(s3 == s4);
这个结果是true,我的理解是这种写法在栈空间里s3和s4其实都是指向堆空间里的“fff”,所以s3就是等于s4的,比较的是他们栈空间的编码,所以相等但是
String s = new String("fff");
String s2 = new String("fff");
System.out.println(s == s2);这样写的话结果就是false,相当于这二个引用虽然都是“fff”,但是指向的其实是堆空间里的2块内存,所以就造成了他们不==,但是我又不理解在这里比较的是什么值?因为我打印以上s1,s2,s3,s4的hashCode,发现都是一样的“101286”看了下api文档,String重写了hashCode()方法
返回此字符串的哈希码。String 对象的哈希码按下列公式计算:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
使用 int 算法,这里 s[i] 是字符串的第 i 个字符,n 是字符串的长度,^ 表示求幂。(空字符串的哈希码为 0。) 那既然所有的“fff”都是一样的hash码,为什么通过new的方式就不等?直接写的方式就等呢?其实也不是什么大的问题,就是搞不明白,有点纠结
s3==s4
s==s2
是检测两个对象的引用是不是指向同一个对象,如果指向同一个对象就返回true,如果不是就返回false.
String s4 = "fff";
System.out.println(s3 == s4);s3和s4是栈内变量,有自己的内存,它们的内存保存的是常量字符串"fff"的地址
==比较的s3和s4变量自身的内存的内容,都是"fff"的地址,所以trueString s = new String("fff");
String s2 = new String("fff");
System.out.println(s == s2);
s和s2是栈内变量,有自己的内存,它们的内存分别保存new String("fff")对象的地址,两个new出来的对象不是同一对象,在堆中有自己的内存地址
==比较的s和s2变量自身的内存的内容,分别是两个new出来的对象的地址,所以不同,即false
String s3 = "fff";这种写法,字符串放进了常量池中。由于这里fff是第一次出现,常量池中没有“fff”,就在里面创建了一个“fff”。之后String s4 = "fff";这回因为常量池中已经有了“fff”,所以s4就指向了和s3一样的地址。所以“==”为true。
new 出来的String是在堆中,String s = new String("fff");你可以换个写法来理解A s = new A("fff");相当于创建了一个A的对象,并给“name”属性赋值为“fff”,所以上面你相当于创建了两个具有相同“name”属性的对象,因为是两个对象,内存地址不一样,所以“==”为false。
字符串确实有点复杂和奇怪下面几种形式是我在书上抄的,与大家一起学习,有理解透彻的达人们可以给讲讲,一起进步。
String hello="Hello";
String lo="lo";
System.out.println(hello=="Hello");
//true 相同包中相同类内的字符串值表示引用相同的String对象
System.out.println(Other.hello==hello);
//true 相同包中不同类内的字符串值表示引用相同的String对象
System.out.println(other.Other.hello==hello);
//true 不同包中不同类内的字符串值也表示引用相同的String对象
System.out.println(hello=="Hel"+"lo");
//true 通过常量表达式计算的字符串是在编译时计算的,然后将它们视为值
System.out.println(hello=="Hel"+lo);
//false 通过串联在运行时计算的字符串的是最新创建的,因此是截然不同的
System.out.println(hello==("Hel"+lo).intern());
//true 显式限定计算过的字符串所带来的结果是:与任何预先存在的字符串值相同的字符串具有相同的内容
==与hashcode无关吧 直接比较地址
String s4 = "fff";
这样定义字符串的方式,是指s3和s4同放在一个字符串堆空间,此时两者的地址是相同的,所以用==的话,返回为true。
2、String s = new String("fff");
String s2 = new String("fff");
System.out.println(s == s2);
这种方式是s和s2为两个不同的引用、占用不同的内存块,当然他们的首地址也不相同,所以毫无疑问,用==比较,返回为false。
在第二个例子里,两个对象都是new出来的,存储在Heap区,两个引用指向不同的对象,也就是不同的内存块,所以地址不相同。
当new一个string对象时,对象的内存地址就不一样了,故返回false