第十八天
相信String這個類是Java中使用得最頻繁的類之一,今天就來和大家一起學習一下String、StringBuilder和StringBuffer。
一、從源碼的角度初步了解String類
想要了解一個類,最好的辦法就是看這個類的實現源代碼,打開這個類的源碼文件就會發現String類是被final修飾的:
進一步分析可以看出幾點:
1)String類是final類,也即意味著String類不能被繼承,并且它的成員方法都默認為final方法。在Java中,被final修飾的類是不允許被繼承的,并且該類中的成員方法都默認為final方法。在早期的JVM實現版本中,被final修飾的方法會被轉為內嵌調用以提升執行效率。而從Java SE5/6開始,就漸漸擯棄這種方式了。因此在現在的Java SE版本中,不需要考慮用final去提升方法調用效率。只有在確定不想讓該方法被覆蓋時,才將方法設置為final。
2)源碼中String類中的成員屬性可以看出,String類其實是通過char數組來保存字符串的。
3)從上面的兩個方法可以看出,無論是sub還是concat操作都不是在原有的字符串上進行的,而是重新生成了一個新的字符串對象。也就是說進行這些操作后,最原始的字符串并沒有被改變。
在這里要永遠記住一點:
“對String對象的任何改變都不影響到原對象,相關的任何change操作都會生成新的對象”。
在了解了于String類基礎的知識后,下面來看一些在平常使用中容易忽略和混淆的地方。
二.深入理解String、StringBuffer、StringBuilder
1.String str="hello world"和String str=new String("hello world")的區別
import java.util.Objects;
public class Demo {
public static void main(String[] args) {
String s1 = "hello";
String s2 = new String("hello");
String s3 = "hello";
String s4 = new String("hello");
System.out.println(s1 == s2);//false
System.out.println(s1 == s3);//true
System.out.println(s2 == s4);//false
}
}
2.String、StringBuffer以及StringBuilder的區別
StringBuffer以及StringBuilder的功能和String一樣都是可以進行字符串的操作。
既然在Java中已經存在了String類,那為什么還需要StringBuilder和StringBuffer類呢?
那么看下面這段代碼:
import java.util.Objects;
public class Demo {
public static void main(String[] args) {
String string = "";
for (int i = 0; i < 100; i++) {
string += "hello";// string = string + hello
//傳統的String做字符串拼接,循環100次,new100字符串對象
}
System.out.println(string);
}
}
從上面String的源碼中我們可以分析出:這句 string += "hello";的過程相當于將原有的string變量指向的對象內容取出與"hello"作字符串相加操作再存進另一個新的String對象當中,再讓string變量指向新生成的對象。也就是說這個循環執行完畢new出了10000個對象,試想一下,如果這些對象沒有被回收,會造成多大的內存資源浪費。
再看下面這段代碼:
import java.util.Objects;
public class Demo {
public static void main(String[] args) {
StringBuilder sbBuilder = new StringBuilder();
for (int i = 0; i < 100; i++) {
sbBuilder.append("hello");
}
System.out.println(sbBuilder.toString());
}
}
這斷代碼和前面的功能一樣,但是這里的10000次循環new操作只進行了一次,也就是說只生成了一個對象,append操作是在原有對象的基礎上進行的。因此在循環了10000次之后,這段代碼所占的資源要比上面小得多。這就是String和stringBuilder的最最主要的區別。
其實:字符串拼接從jdk5開始編譯器就已經完成了自動優化,當String+常量的代碼在編譯的時候就會自動被優化為new一個StringBuilder,再調用append方法。
那么有人會問既然有了StringBuilder類,為什么還需要StringBuffer類?查看源代碼便一目了然,事實上,StringBuilder和StringBuffer類擁有的成員屬性以及成員方法基本相同,區別是StringBuffer類的成員方法前面多了一個關鍵字:synchronized,不用多說,這個關鍵字是在多線程訪問時起到安全保護作用的,也就是說StringBuffer是線程安全的。有關線程的問題,我們講多線程的時候在詳細講解!
總結:這三個類是各有利弊,應當根據不同的情況來進行選擇使用
1、循環外字符串拼接可以直接使用String的+操作,沒有必要通過StringBuilder進行append.
2、有循環體的話,好的做法是在循環外聲明StringBuilder對象,在循環內進行手動append。
不論循環多少層都只有一個StringBuilder對象。
3、當字符串相加操作較多的情況下,建議使用StringBuilder,如果采用了多線程,則使用StringBuffer。
相信String這個類是Java中使用得最頻繁的類之一,今天就來和大家一起學習一下String、StringBuilder和StringBuffer。
一、從源碼的角度初步了解String類
想要了解一個類,最好的辦法就是看這個類的實現源代碼,打開這個類的源碼文件就會發現String類是被final修飾的:
進一步分析可以看出幾點:
1)String類是final類,也即意味著String類不能被繼承,并且它的成員方法都默認為final方法。在Java中,被final修飾的類是不允許被繼承的,并且該類中的成員方法都默認為final方法。在早期的JVM實現版本中,被final修飾的方法會被轉為內嵌調用以提升執行效率。而從Java SE5/6開始,就漸漸擯棄這種方式了。因此在現在的Java SE版本中,不需要考慮用final去提升方法調用效率。只有在確定不想讓該方法被覆蓋時,才將方法設置為final。
2)源碼中String類中的成員屬性可以看出,String類其實是通過char數組來保存字符串的。
3)從上面的兩個方法可以看出,無論是sub還是concat操作都不是在原有的字符串上進行的,而是重新生成了一個新的字符串對象。也就是說進行這些操作后,最原始的字符串并沒有被改變。
在這里要永遠記住一點:
“對String對象的任何改變都不影響到原對象,相關的任何change操作都會生成新的對象”。
在了解了于String類基礎的知識后,下面來看一些在平常使用中容易忽略和混淆的地方。
二.深入理解String、StringBuffer、StringBuilder
1.String str="hello world"和String str=new String("hello world")的區別
publicclassMain {
publicstaticvoidmain(String[] args) {
String str1 ="hello world";
String str2 =newString("hello world");
String str3 ="hello world";
String str4 =newString("hello world");
System.out.println(str1==str2);
System.out.println(str1==str3);
System.out.println(str2==str4);
}
}
這段代碼的輸出結果為
2.String、StringBuffer以及StringBuilder的區別
StringBuffer以及StringBuilder的功能和String一樣都是可以進行字符串的操作。
既然在Java中已經存在了String類,那為什么還需要StringBuilder和StringBuffer類呢?
那么看下面這段代碼:
publicclassMain {
publicstaticvoidmain(String[] args) {
String string ="";
for(inti=0;i<10000;i++){
string +="hello";
}
}
}
從上面String的源碼中我們可以分析出:這句 string += "hello";的過程相當于將原有的string變量指向的對象內容取出與"hello"作字符串相加操作再存進另一個新的String對象當中,再讓string變量指向新生成的對象。也就是說這個循環執行完畢new出了10000個對象,試想一下,如果這些對象沒有被回收,會造成多大的內存資源浪費。
再看下面這段代碼:
publicclassMain {
publicstaticvoidmain(String[] args) {
StringBuilder stringBuilder =newStringBuilder();
for(inti=0;i<10000;i++){
stringBuilder.append("hello");
}
}
}
這斷代碼和前面的功能一樣,但是這里的10000次循環new操作只進行了一次,也就是說只生成了一個對象,append操作是在原有對象的基礎上進行的。因此在循環了10000次之后,這段代碼所占的資源要比上面小得多。這就是String和stringBuilder的最最主要的區別。
其實:字符串拼接從jdk5開始編譯器就已經完成了自動優化,當String+常量的代碼在編譯的時候就會自動被優化為new一個StringBuilder,再調用append方法。
那么有人會問既然有了StringBuilder類,為什么還需要StringBuffer類?查看源代碼便一目了然,事實上,StringBuilder和StringBuffer類擁有的成員屬性以及成員方法基本相同,區別是StringBuffer類的成員方法前面多了一個關鍵字:synchronized,不用多說,這個關鍵字是在多線程訪問時起到安全保護作用的,也就是說StringBuffer是線程安全的。有關線程的問題,我們講多線程的時候在詳細講解!
總結:這三個類是各有利弊,應當根據不同的情況來進行選擇使用
1、循環外字符串拼接可以直接使用String的+操作,沒有必要通過StringBuilder進行append.
2、有循環體的話,好的做法是在循環外聲明StringBuilder對象,在循環內進行手動append。
不論循環多少層都只有一個StringBuilder對象。
3、當字符串相加操作較多的情況下,建議使用StringBuilder,如果采用了多線程,則使用StringBuffer。
總結
- 上一篇: 崩坏星穹铁道托帕抽几命
- 下一篇: app中的弹窗—(对话框,动作菜单,浮出