Java基礎16-String類(Buffer和Builder)
一、String類的本質是什麽?
上邊代碼竟然輸出的是一樣的,我們進到String類的源碼中
其實,字符串的本質就是字符數組, String 其實就是char數組的封裝
二、字符串的分類
1.不可變得字符串String:當前對象創建完畢之後,該對象的內容是不能改變的,一旦內容改變就是一個新的類
2.可變的字符串:StringBuffer/StringBuilder,當前內容創建完畢之後,該對象的內容可以發生改變,內容改變時對象不變
我們輸出上邊兩段代碼,雖然引用名稱相同,但是當我們重新賦值時,它的hashcode發生了變化,也就是說,str在內存中的地址發生了變化,str="索隆"雖然與str="路飛"名稱相同,但實則是兩個變量,也就是重新在內存中(常量池)開辟了一塊空間
三、String對象的創建
1.直接賦一個字面量:
String str1="abcd";
2.通過構造器
String str2=new String("abcd");
這兩者有什麽區別呢?別著急,請看下文
要說這個問題,那就必須要來了解一個內存中的區域,常量池。
常量池:專門存儲常量的地方,都指的方法區中
* 編譯常量池:把字節碼加載進jvm時,存儲的是字節碼的相關信息(不研究)
* 運行常量池:存儲常量數據(研究)
通過這個問題我們就來揭曉
String str4="abcd"和String str5=new String("abcd")的區別?
以上代碼創建了幾個String對象呢?
str4最多創建一個,最少不創建,如果常量池中已經存在abcd,直接引用不創建
str5最多創建兩個String對象,至少創建一個,new關鍵字絕對會在堆空間創建內存區域,所以至少創建一個
我們再回頭看第二種的hashcode不同的問題,實際上就是不同的值在常量池中開辟的空間其地址不同,當值變了。也就是這個引用指向的地址發生了變化
str和str10的hashcode竟然是一樣的! 這下我們就明白了吧,只要是值相同,不管叫什麽名字都指向的是同一個地址。
四、String對象的空值
1.表示引用為空(null):沒有初始化,沒有分配內存空間
String str3=null;
2.內容為空,已經初始化,分配了內存空間,不過沒有內容
五、判斷字符串非空
1.引用不能為空(null)
2.字符內容不能為空字符串
六、字符串的比較操作
1.使用==運算符,只能比較引用的內存地址是否相同
2.使用equals方法:在object類中和==相同,建議子類覆蓋equals方法去比較內容
七、字符串的比較
1.單獨使用""創建的字符串都是直接量,編譯器已經確定存儲到常量池中
2.使用new String("")創建的對象會存儲到堆內存中,運行時期才創建
3.使用只包含直接量的字符串連接符如"aa"+"bb"創建的也是直接量,編譯器就能確定,已經存儲到常量池中
4.使用包含String直接量(無final修飾符)的字符串表達式(如"aa"+s1)創建的對象是運行期才創建的,存儲在堆中
八、常用方法聯系
//一、String練習,獲取hello開頭的文件名的後綴名 String filename="abc.java;hello.java"; //1.一份好來分割字符串,獲取每個的名稱和拓展名 String[] name=filename.split(";"); for (String names : name) { System.out.println(names); //2.判斷每個名稱是否以hello開頭 if(names.startsWith("hello")) { //3.獲取文件名的後綴名,最後一個點的後半截 names.lastIndexOf("."); //截取字符串 System.out.println(names.substring(names.lastIndexOf("."))); } } //二、單詞首字母大寫 String str7="willabcad"; //1.獲取第一個字符,轉換為大寫 String first=str.substring(0, 1).toUpperCase(); //2.截取字符串從1到最後 String last=str.substring(1); System.out.println(first+last); //trim方法消除前後空格 System.out.println(" ab cd ".trim().length()); System.out.println(" ab cd ".length());
九、StringBuilder和StringBuffer
先來看一個小例子
//使用String/StringBuilder和StringBuffer拼接3萬次 long begin=System.currentTimeMillis(); String str8=""; for(int i=0;i<30000;i++) { str8+=i; } long end=System.currentTimeMillis(); System.out.println(end-begin); //string做字符串拼接性能很低,原因是每次都要new新的對象 StringBuffer sb=new StringBuffer(""); long begin2=System.currentTimeMillis(); for(int i=0;i<30000;i++) { sb.append(i); } long end2=System.currentTimeMillis(); System.out.println(end2-begin2); StringBuilder sbr=new StringBuilder(""); long begin3=System.currentTimeMillis(); for(int i=0;i<30000;i++) { sbr.append(i); } long end3=System.currentTimeMillis(); System.out.println(end3-begin3); }
經過測試,sbr耗時最短,sb次之,所以拼接字符串使用stringbuffer或者stringbuilder
StringBuilder和StringBuffer都表示可變的字符串,功能方法相同
唯一的區別;
stringbuffer:使用了synchronized修飾符,表示同步,再多錢程並發時保證線程安全
stringbuilder:沒有synchronized,不安全
常用操作
鏈式編程
append,deleteCharAt
Java基礎16-String類(Buffer和Builder)