引言
当你看到本博客的标题时,你是否会感觉到疑惑?疑惑为什么一个简简单单的字符串拼接和比较也要写。你要是这么想就错了,其实,字符串拼接也藏着些许的小秘密。通过以下几个实例后,你就能够清楚的了解字符串拼接和比较的“秘密”了。
实例1
public static void main(String[] args) {
String aString = "123";
String bString = "123";
System.out.println(aString == bString);
}
输出:true
当我们使用双引号创建一个字符串时,JVM 首先在字符串池中寻找具有相同值的字符串。如果找到了,它将返回字符串池中的字符串对象的地址。否则,它会在字符串池中创建字符串对象并返回地址。
对于本例,aString先在字符串常量池中搜寻过,没发现字符串123,于是开辟了空间存放字符串123,然后aString指向该空间地址。同样,bString搜寻了一下,找到了字符串123,然后bString指向该空间地址。所以最后结果为 true
实例2
public static void main(String[] args) {
String astring = new String("123");
String bString = "123";
System.out.println(astring == bString);
}
输出结果:false
当我们用new关键字创建字符串对象时,会先在我们的堆内存当中开辟一段内存空间,然后该内存空间会用来存储我们在字符串常量池当中的数据地址。
实例3
public static void main(String[] args) {
String aString = "1";
String bString =aString+"23";
String cString = "123";
System.out.println(bString == cString);
String dString ="1"+"23";
System.out.println(dString == cString);
}
输出:
为什么 bString 和 cString 都是字符串123,但是结果为 false?
下面我们用记事本写一个java文件,然后命令窗口进行编译和反编译:
我们可以注意到,当我们使用“+”号进行字符串拼接的时候其实我们调用的是StringBuilder中的两个方法,append和toString方法。使用append进行拼接,拼接字符串后,虚拟机调用StringBuilder的toString()方法输出字符串的“123”,然后该值存放至bString。
那么这个拼接好的“123”到底是以什么形式传递给bString的呢?我们来看toString方法。
@Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
ok,我们可以很清楚的看到,是一个new String。所以第一个结果为false
为什么第二个输出的是true?
因为jvm编译阶段过编译器优化后会把字符串常量直接合并成"123",并没有开辟新的空间,所以dString和cString指的是同一个地址
所以,你清楚了字符串的“秘密”了吗?