媒介
有这么一段代码:
public class TestMain { public static void main(String[] args) { String str0 = "123"; String str1 = "123"; System.out.println(str0 == str1); } }
运行功效是什么?谜底虽然是true。对,谜底简直是true,可是这是为什么呢?许多人第一回响必定是两个”123″的String虽然相等啊,这还要想。可是”==”在Java较量的不是两个工具的值,而是较量两个工具的引用是否相等,和两个String都是”123″又有什么干系呢?可能我们把措施修改一下
public class TestMain { public static void main(String[] args) { String str2 = new String("234"); String str3 = new String("234"); System.out.println(str2 == str3); } }
这时候运行功效就是false了,因为尽量两个String工具都是”234″,可是str2和str3是两个差异的引用,所以返回的false。OK,环绕第一段代码返回true,第二段代码返回false,开始文章的内容。
为什么String=String?
在JVM中有一块区域叫做常量池,关于常量池,我在写虚拟机的时候有专门提到http://www.cnblogs.com/xrq730/p/4827590.html。常量池中的数据是那些在编译期间被确定,并被生存在已编译的.class文件中的一些数据。除了包括所有的8种根基数据范例(char、byte、short、int、long、float、double、boolean)外,尚有String及其数组的常量值,别的尚有一些以文本形式呈现的标记引用。
Java栈的特点是存取速度快(比堆块),可是空间小,数据生命周期牢靠,只能保留到要领竣事。我们界说的boolean b = true、char c = ‘c’、String str = “123”,这些语句,我们拆分为几部门来看:
1、true、c、123,这些等号右边的指的是编译期间可以被确定的内容,都被维护在常量池中
2、b、c、str这些等号左边第一个呈现的指的是一个引用,引用的内容是等号右边数据在常量池中的地点
3、boolean、char、String这些是引用的范例
栈有一个特点,就是数据共享。回到我们第一个例子,第五行String str0 = “123″,编译的时候,在常量池中建设了一个常量”123″,然后走第六行String str1 = “123″,先去常量池中找有没有这个”123″,发明有,str1也指向常量池中的”123″,所以第七行的str0 == str1返回的是true,因为str0和str1指向的都是常量池中的”123″这个字符串的地点。虽然假如String str1 = “234″,就又纷歧样了,因为常量池中没有”234″,所以会在常量池中建设一个”234″,然后str1代表的是这个”234″的地点。阐明白String,其实其他根基数据范例也都是一样的:先看常量池中有没有要建设的数据,有就返回数据的地点,没有就建设一个。
第二个例子呢?Java虚拟机的表明器每碰着一个new要害字,城市在堆内存中开发一块内存来存放一个String工具,所以str2、str3指向的堆内存中固然存储的是相等的”234″,可是由于是两块差异的堆内存,因此str2 == str3返回的仍然是false,网上找到一张图暗示一下这个观念:
为什么要利用StringBuilder和StringBuffer拼接字符串?
各人在开拓中必然有一个原则是”操作StringBuilder和StringBuffer拼接字符串”,可是为什么呢?用一段代码来阐明一下:
public class StringTest { @Test public void testStringPlus() { String str = "111"; str += "222"; str += "333"; System.out.println(str); } }
这段代码,我们找到编译后的StringTest.class文件,利用”javap -verbose StringTest”可能”javap -c StringTest”都可以,反编译一下class获取到对应的字节码:
public void testStringPlus(); Code: 0: ldc #17 // String 111 2: astore_1 3: new #19 // class java/lang/StringBuilder 6: dup 7: aload_1 8: invokestatic #21 // Method java/lang/String.valueOf:(Ljava/lang/Object;)L java/lang/String; 11: invokespecial #27 // Method java/lang/StringBuilder."<init>":(Ljava/lang/S tring;)V 14: ldc #30 // String 222 16: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/Str ing;)Ljava/lang/StringBuilder; 19: invokevirtual #36 // Method java/lang/StringBuilder.toString:()Ljava/lang/ String; 22: astore_1 23: new #19 // class java/lang/StringBuilder 26: dup 27: aload_1 28: invokestatic #21 // Method java/lang/String.valueOf:(Ljava/lang/Object;)L java/lang/String; 31: invokespecial #27 // Method java/lang/StringBuilder."<init>":(Ljava/lang/S tring;)V 34: ldc #40 // String 333 36: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/Str ing;)Ljava/lang/StringBuilder; 39: invokevirtual #36 // Method java/lang/StringBuilder.toString:()Ljava/lang/ String; 42: astore_1 43: getstatic #42 // Field java/lang/System.out:Ljava/io/PrintStream; 46: aload_1 47: invokevirtual #48 // Method java/io/PrintStream.println:(Ljava/lang/String ;)V 50: return }