String的兩種創建方式+StringBuffer+StringBuilder

一:String
直接賦值和使用new的區別

String str = new String();
此時JVM

在這裏插入圖片描述

Demo_01_String

//直接賦值
String str1 = "hello";
String str2 = "hello";
String str3 = "world";
System.out.println("string==:"+(str1 == str2));//true:二者都指向常量池中同一對象,其地址值相同
System.out.println("string==:"+(str2 == str3));//false
System.out.println("string.equals:"+str1.equals(str2));//true
System.out.println("str1地址:"+str1.hashCode());	//99162322
System.out.println("str2地址:"+str2.hashCode()); //99162322
System.out.println("str3地址:"+str3.hashCode()); //113318802

// new String
String str4 = new String("hello");
String str5 = new String("hello");
String str6 = new String("world");
System.out.println("string==:"+(str1 == str4));//false:存放的地址不同
System.out.println("string==:"+(str4 == str5));//false:比較兩個包裝類的引用是否指向同一個對象,即在堆中的地址是否相同
System.out.println("string.equals:"+str1.equals(str4));//true 比較引用類型的值是否相等
System.out.println("string.equals:"+str4.equals(str5));//true
System.out.println("str4地址:"+str4.hashCode());	//99162322
System.out.println("str5地址:"+str5.hashCode());	//99162322
System.out.println("str6地址:"+str6.hashCode());	//113318802

//字符串相加
String strConst = str2 + str3;//是先加,然後在常量池找
String strNew = str5 + str6;//先開空間,再拼接
System.out.println(strConst.hashCode());
System.out.println(strNew.hashCode());
System.out.println("字符串相加後比較:"+(strConst == strNew));	//
System.out.println("字符串相加後比較:"+strConst.equals(strNew));

str4和str5對同一個對象的引用

Demo_02_StringBuffer

StringBuffer sbf1 = new StringBuffer("hello");
StringBuffer sbf2 = new StringBuffer("hello");
StringBuffer sbf3 = new StringBuffer("world");
System.out.println("stringBuffer==:"+(sbf1 == sbf2));	//false
System.out.println("stringBuffer.equals:"+sbf1.equals(sbf2));	//false
System.out.println("stringBuffer.equals:"+sbf2.append(sbf3));	//拼接

Demo_03_StringBuilder

StringBuilder sbu1 = new StringBuilder("hello");
StringBuilder sbu2 = new StringBuilder("hello");
StringBuilder sbu3 = new StringBuilder("world");
System.out.println("stringBuilder==:"+(sbu1 == sbu2));	//false
System.out.println("stringBuilder.equals:"+sbu1.equals(sbu2))	//false
System.out.println("stringBuilder.equals:"+sbu2.append(sbu3));
  1. 由於String變量實際上是對一個String對象的引用(指向常量池),所以兩個通過new生成的String變量永遠是不相等的(因爲new生成的是兩個對象,其(在堆中的)內存地址不同)。
  2. String是final類,其值是不可變的,看以下板栗,只是改變了賦值地址;
// 1. 重新賦值
String str1 = "hello";
System.out.println("str1原本地址:"+str1.hashCode());	//99162322
str1 = "java";
System.out.println("str1改變後的地址:"+str1.hashCode());	//3254818

重新賦值後str1指向新地址,但舊地址中保存的"world"依舊存在,但已經不再是str1所指向的,str1已經指向了其它地址。
所有對String類型進行改變的時候都會重新生成一個新的String對象,如果字符串的內容經常改變,而且不考慮多線程的話,建議使用StringBuilder

// 2. 字符串拼接後地址有無改變?
	    String strConst = str2 + str3;//是先加,然後在常量池找
		String strNew = str5 + str6;//先開空間,再拼接
		System.out.println("字符串拼接後的地址:"+strConst.hashCode()); //變成-1524582912
		System.out.println("字符串拼接後的地址:"+strNew.hashCode());	//變成-1524582912
		
	    System.out.println("sbf3原本地址:"+sbf3.hashCode());	//27134973
		System.out.println("sbf3拼接後:"+sbf2.append(sbf3));
		System.out.println("sbf3拼接後的地址:"+sbf3.hashCode());	//還是sbf3的地址27134973

查看源碼可知String重寫了equals()方法,但StringBuffer和StringBuilder沒有

看JDK怎麼說

StringBuffer

  1. 是線程安全的可變字符序列,可將字符串緩衝區安全地用於多個線程,可以在必要時對這些方法進行同步;
  2. 主要操作是 append 和 insert 方法;
  3. 沒有重寫equals方法

StringBuilder

  1. 此類提供一個與 StringBuffer 兼容的 API,但不保證同步;
  2. 該類被設計用作 StringBuffer 的一個簡易替換,用在字符串緩衝區被單個線程使用的時候,這樣比buffer快
  3. 主要操作和buffer一樣
  4. 沒有重寫equals方法

總結

  1. String = 操作少量的數據
  2. StringBuilder = 單線程操作字符串緩衝區 下操作大量數據;線程非安全的
  3. StringBuffer = 多線程操作字符串緩衝區 下操作大量數據;線程安全的
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章