String類實例對象的不可變性:
String的兩種聲明方式:
- 方式1:我們經常使用的字符串聲明方式聲明其對象:
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);//true
- 方式2:通過new對象的方式:
String s1= new String("abc");
String s2= new String("abc");
System.out.println(s1 == s2);//false
(1)這兩種聲明方式在內存中是不同的,首先String類是一個final類第一種方式相當於:
final String s1 = "abc"
可見相當於定義了一個字符串常量,在內存中擁有一個特殊的空間用來存放該常量,該常量的值是不可以被改變的(String的不可變性1);當創建該常量的時候jvm對判斷內存中是否存在該常量,如果沒有則創建,有則只創建一個新的引用指向該常量。
(2)通過第二種方式創建,與其他類相同,new一個新的對象則在堆內存中開闢一個空間,方式2 new了兩個對象,雖然對象內容一樣但是內存地址不同,而==操作符比較的就是兩個對象的首內存地址,所以結果爲false;
String類生成對象可以被修改,但是修改後將返回一個新的對象。
用上述兩種方法創建的字符串,都是可以使用concat方法來修改對象內容,字符串被修改後將返回一個新的字符串。
- 方式1相當於又生成一個字符串常量,
- 方式2相當於有生成個字符串對象;
所以如果用==比較的話,兩種方式新生成的字符串與之前的字符串均不相同;
String對“+”的重載
我們知道,Java是不支持重載運算符,String的“+”是java中唯一的一個重載運算符,那麼java使如何實現這個加號的呢?我們先看一段代碼:
public static void main(String[] args) {
String string=”hollis”;
String string2 = string + “chuang”;
}
然後我們將這段代碼反編譯:
public static void main(String args[]){
String string = “hollis”;
String string2 = (new StringBuilder(String.valueOf(string))).append(“chuang”).toString();
}
看了反編譯之後的代碼我們發現,其實String對“+”的支持其實就是使用了StringBuilder以及他的append、toString兩個方法。
這裏可以看到先new了一個StringBuilder對象,這時候就在堆內存中創建了一個對象,而String2指向的是這個對象的內存地址。所以和String指向的地址不同。
String字符串的格式化輸出:
方法1:可以使用system.out.printf語句格式化輸出String字符串;
System.out.printf("The value of the float variable is " + "%f, while the value of the integer " + "variable is %d, and the string " + "is %s", float類型變量, int類型變量, string類型變量);
方法2:也可以採用String類的format方法,格式化生成字符串對象;
String fs;//先格式化生成fs對象 fs = String.format("The value of the float variable is " + "%f, while the value of the integer " + "variable is %d, and the string " + "is %s", float類型變量, int類型變量, string類型變量); System.out.println(fs);//後打印輸出該字符串
String的比較方法:
- 方法1 “s1 == s2” 比較兩者所指向的對象內存地址是否相同;
方法2 “s1.equal(s2)”覆寫了Object類中的equal()方法;
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) {//判斷比較對象是否是String對象類型 String anotherString = (String) anObject; int n = value.length; if (n == anotherString.value.length) {//如果兩個string對象的長度相同進行下面的比較; char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) {//比較所有字符是否相同,v[i] 等於該字符的Unicode表中對應的數值; if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
方法3: compareto()方法:
public int compareTo(String anotherString) { int len1 = value.length; int len2 = anotherString.value.length; int lim = Math.min(len1, len2); char v1[] = value;//String類的本質是字符數組char[] char v2[] = anotherString.value; int k = 0; while (k < lim) { char c1 = v1[k]; char c2 = v2[k]; if (c1 != c2) { return c1 - c2; } k++; } return len1 - len2; }
return
- the value 0 if the argument string is equal to this string;
- a value less than 0 if this string is lexicographically less than the string argument; and a
- value greater than 0 if this string is lexicographically greater than the string argument.
也就是如果兩個字符串相同的返回0,若兩個字符串不相同的話返回第一個不相同字符的unicode編碼值的差值。
參考資料:
java String對象的經典問題 http://sarin.iteye.com/blog/603684