標籤:mem 可變 鏈式編程 轉換 同步 操作 聯絡 輸出 方法
一、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)