文章目錄
一、字元串常量池
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
String s4 = new String("abc");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s3 == s4);
}
上面兩種建立String對象的方式相同嗎?
在Java程式中,“ ”雙引号引起來的字面類型的常量經常頻繁使用,為了使程式的運作速度更快、更節省記憶體,Java為8種基本資料類型和String類都提供了常量池。
1.使用字元常量直接指派:
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);
}
在直接用字面常量指派String時,先在常量池裡找,是否有這個字元串,如果沒有則建立,我們發現常量池并沒有abc,是以我們建立一個“abc”。
當第二次建立"abc"字元串賦給s2時直接指向就行.
s1和s2指向的是同一塊引用,是以s1 == s2。
2.通過new建立String類對象:
隻要new對象,它的引用就是唯一的.
使用常量串建立String類型對象的效率更高,而且更節省空間。
3.intern方法:
intern 是一個native方法(Native方法指:底層使用C++實作的,看不到其實作的源代碼),該方法的作用是手動将建立的String對象添加到常量池中。
public static void main(String[] args) {
char[] ch = new char[]{
'a','b','c'};
String s1 = new String(ch);
String s2 = "abc";
System.out.println(s1 == s2);
}
我們可見s1 和 s2指向不同的引用
public static void main(String[] args) {
char[] ch = new char[]{
'a','b','c'};
String s1 = new String(ch);
s1.intern();
String s2 = "abc";
System.out.println(s1 == s2);
}
intern()方法是将s1中的引用放入常量池中.當s2建立時,就會指向常量池的那個引用.
二、字元串的不可變性
String是一種不可變對象. 字元串中的内容是不可改變。
String的源碼中,注解中寫到String是一個常量,不可修改.
我們在來看String類型是如何存儲字元串的
可能有人說因為被final修飾,是以不能修改,首先這是一個很大的誤區,final修飾隻能說明value引用的對象不能修改,而不是說value引用的值不能修改.
我們随便打開一個String的方法,這裡打開的是toUpperCase方法,可以發現:所有涉及到修改字元串内容的方法都是建立一個新對象傳回.
String為什麼要設計成不可變的?
- 友善實作字元串對象池. 如果 String 可變, 那麼對象池就需要考慮寫時拷貝的問題了.
- 不可變對象是線程安全的.
- 不可變對象更友善緩存 hash code, 作為 key 時可以更高效地儲存到 HashMap 中.
三、字元串修改
字元串是不能修改的,每次修改都會建立新對象,效率非常低下.
public static void main(String[] args) {
String str = "wo"+"yao"+"jin"+"da"+"chang";
System.out.println(str);
}
當然是可以正常輸出的,我們看一下彙編.
我們會發現建立了許多StringBuilder對象,去拼接字元串,這樣效率十分低下。
public static void main(String[] args) {
long start = System.currentTimeMillis();
String s = "";
for(int i = 0; i < 10000; ++i){
s += i;
}
long end = System.currentTimeMillis();
System.out.println(end - start);
start = System.currentTimeMillis();
StringBuffer sbf = new StringBuffer("");
for(int i = 0; i < 10000; ++i){
sbf.append(i);
}
end = System.currentTimeMillis();
System.out.println(end - start);
start = System.currentTimeMillis();
StringBuilder sbd = new StringBuilder();
for(int i = 0; i < 10000; ++i){
sbd.append(i);
}
end = System.currentTimeMillis();
System.out.println(end - start);
}
我們發現在對String進行修改時,String與StringBuffer和StringBuilder相差幾百倍.
四、StringBuilder與StringBuffer的方法
這裡都是StringBuffer和StringBuilder的一些方法.
1.append
拼接字元串
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("wo yao jin da chang!");
System.out.println(stringBuilder);
}
2.reverse
字元串逆置
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("abcd");
stringBuilder.reverse();
System.out.println(stringBuilder);
}
3.delete
删除指定範圍内的字元
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("abcd");
stringBuilder.delete(0,2);
System.out.println(stringBuilder);
}
String與StringBuilder互相轉換:
String和StringBuilder最大的差別在于String的内容無法修改,而StringBuilder的内容可
以修改。頻繁修改字元串的情況考慮使用StringBuilder
1.String變為StringBuilder
public static void main(String[] args) {
//調用StringBuilder構造方法
String str = "abc";
StringBuilder stringBuilder = new StringBuilder(str);
}
public static void main(String[] args) {
//append拼接字元串
String str = "abc";
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(str);
System.out.println(stringBuilder);
}
1.StringBuilder變為String
我們可以看一下StringBuilder的toString()方法傳回的是一個String對象.
public static void main(String[] args) {
//StringBuilder的toString()方法
StringBuilder stringBuilder = new StringBuilder("abc");
String str = stringBuilder.toString();
System.out.println(str);
}
四、StringBuilder與StringBuffer差別
String、StringBuffer、StringBuilder的差別:
1.String的内容不可修改,StringBuffer與StringBuilder的内容可以修改.
2.StringBuffer與StringBuilder大部分功能是相似的
3.StringBuffer采用同步處理,屬于線程安全操作;而StringBuilder未采用同步處理,屬于線程不安全操作
StringBuffer中的每個方法加入了synchronized,它就相當于是一把鎖,隻要有第一個人通路這個方法,那麼這個方法就隻能等第一個人通路完成之後,剩下的人才能通路.
String str = new String("abc");
String str = new String("ab") + new String("c");