1. 字符串创建
在我们的JVM中,有常量池-存放字符串、堆-存放new的字符串、栈-存放引用地址
我们看一下创建字符串的两种方式:
String s1 = "china"; String s2 = "china"; String s3 = "china"; String ss1 = new String("china"); String ss2 = new String("china"); String ss3 = new String("china");
- 对于第一种创建:在我们的常量池中创建出一个"china"的字符串,在栈中将s1、s2、s3指向其常量池
- 对于第二种创建:首先去我们的常量池中寻找有没有"china"字符串,没有则创建,再去我们的堆进行对象的创建,在栈中将ss1、ss2、ss3指向堆中
2. 字符串比较
2.1 普通比较
String str1 = "a"; String str2 = "b"; String str3 = "ab"; String str4 = str1 + str2; String str5 = new String("ab"); String str6 = "a" + "b"; System.out.println(str5.equals(str3)); System.out.println(str5 == str3); System.out.println(str4 == str3); System.out.println(str5.intern() == str3); System.out.println(str5.intern() == str4); System.out.println(str5.intern() == str6); System.out.println(str3 == str6);
先想想自己的答案:
依次分析:
首先看下创建的过程
String str1 = "a";
直接常量池创建"a",栈创建str1指向- 同上
- 同上
String str4 = str1 + str2;
,因为我们的JVM没有办法将str1和str2自动识别成字符串,所以会将他们new 一个放置在堆内存中String str5 = new String("ab");
直接创建即可String str6 = "a" + "b";
我们的JVM先将"a" + “b"变成"ab”,再去赋值给str6
比较过程:
前面的不说了,重点说一下关于:System.out.println(str5.intern() == str3);
官方API:
intern
public String intern()
返回字符串对象的规范化表示形式。
一个初始时为空的字符串池,它由类 String 私有地维护。
当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。
它遵循对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。
所有字面值字符串和字符串赋值常量表达式都是内部的。
返回:一个字符串,内容与此字符串相同,但它保证来自字符串池中。
上面的理解比较官方,简单来说就是,我调用了这个函数,你给我返回一个存在于常量池中的字符串,要是没有,你给我加一个
比如:str5.intern()就是调用的常量池中的ab字符串,也就是只要指向ab字符串的,就可以判定为true
System.out.println(str5.equals(str3)); System.out.println(str5 == str3); System.out.println(str4 == str3); System.out.println(str5.intern() == str3); System.out.println(str5.intern() == str4); System.out.println(str5.intern() == str6); System.out.println(str3 == str6);
答案分别是:
true
false
false
true
false
true
true
2.2 final比较
看完上面的,是不是感觉自己超级牛逼,感觉啥都懂了
别慌 看这个
final String str1 = "a"; final String str2 = "b"; String str3 = "ab"; String str4 = str1 + str2; System.out.println(str4 == str3);
按照咱们上面说的,这个不细心的可能直接就false了
细心的看到对于str1和str2被final修饰了
回想一下,final修饰变量的作用,不可变性对吧。
如果被final修饰后,JNM在使用的时候,会把他当成一个字符串来使用,也就是类似于"a" + "b"这种操作,所以,最后的值是true
3. 总结
画图---->记住intern引用---->final变量
字符串比较不过如此~简简单单