您好,登錄后才能下訂單哦!
這篇文章主要介紹“Java中String類的使用方法有哪些”,在日常操作中,相信很多人在Java中String類的使用方法有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java中String類的使用方法有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
創建字符串的方式有三種:
// 方式一 String str = "Hello Bit"; // 方式二 String str2 = new String("Hello Bit"); // 方式三 char[] array = {'a', 'b', 'c'}; String str3 = new String(array);
我們對第一和第二種創建字符串的方法都已經非常熟悉了,那至于為什么第三種能夠傳入一個字符數組變為字符串,我們可以按住ctrl鍵點入傳入字符數組的String當中看其原碼,我們能夠發現此時是利用的方法是數組的拷貝,將字符數組的所有字符改為字符串形式。
因為字符串等同于是一個個字符的集合,因此要想字符轉為字符串則要調用String的構造方法并傳入一個字符數組。例如:
char[] val = {'a','b','c'}; String str = new String(val); System.out.println(str);
當然,我們也可以選擇字符數組從哪個下標開始到哪個下標結束的字符轉換為字符串的形式。
例如:
char[] val = {'a','b','c','d','e'}; String str1 = new String(val,0,3); System.out.println(str1); //打印結果為abc System.out.println("========="); String str2 = new String(val,1,3); System.out.println(str2); //打印結果為bcd
因為字符串是字符的集合,因此可以字符串可以轉換為一個字符或者一個字符數組。括號內的比如0、1是偏移量,偏移量是從0開始的,因此從偏移量為0的位置處往后取3個字符構成一個字符串。
如果字符串要轉換為單個字符,代碼如下:
String str = "abc"; System.out.println(str.charAt(1)); //打印結果為b
如果字符串要轉換為字符數組,代碼如下:
char[] val = str.toCharArray(); System.out.println(Arrays.toString(val)); //打印結果:[a, b, c]
Java中的將字節轉為字符串需要將字節數組轉為字符串。
字節數組轉換為字符串:
byte[] bytes = {97,98,99,100}; String str1 = new String(bytes,0,3); System.out.println(str1); //打印結果為abc System.out.println("========"); String str2 = new String(bytes,1,3); System.out.println(str2); //打印結果為bcd
字符串轉換為字節數組:
String str1 = "abc"; byte[] bytes1 = str1.getBytes(); System.out.println(Arrays.toString(bytes1)); //打印結果為:[97, 98, 99]
有許多初學者會認為,“ == ”與equals比較的方式是相同的。其實有很大的區別。
對于兩個字符串用“ == ”比較,比較的是變量的引用。而String的equals方法比較的是兩個字符串的內容。但此時又有個疑問:為什么每個定義字符串常量的是一個引用呢?這樣就牽扯到了字符串常量池。
對于“池”這個概念,可能大家還是比較陌生的。比如數據連接池、線程池等等。那這些池的作用的干嘛的呢?是用來提高存儲效率的。顧名思義字符串常量池是用來存儲字符串常量的。字符串常量池中規定只要有了一個字符串常量就不再存儲相同的字符串了。從JDK1.8開始字符串常量池是在堆里的。它本質上是一個哈希表(StringTable)是一個數組。存儲字符串常量是,會根據一個映射關系進行存儲,這個映射關系需要設計一個哈希函數。(因為字符串常量池是有關于JVM的,需要看其原碼才能真正了解字符串常量池是如何操作的,此處不深究其原理也不會影響我們判斷引用是否相同)。
字符串常量池中當存儲一個字符串常量時會在根據哈希函數計算的某一個位置處產生一個結點,結點是由哈希值、String結點的地址、存儲該數組位置處的下一個結點的地址組成的(這在JVM的原碼中才能真正了解)。而每一個String結點是由字符型數組value與哈希值hash(默認為0)構成的 (下圖所示)。點入String看其原碼時就能夠會發現這兩個變量。此時觀察到value數組被final修飾則說明該數組里的字符是不能夠被改變的,這就是字符串是一個常量的原因,并且該字符串會轉換為字符形式存放在字符數組當中。
先來舉一個比較簡單的例子來理解字符串常量池的內存布局。
代碼如下:
代碼一:
String str1 = "hello"; String str2 = "hello"; System.out.println(str1==str2); //打印結果為true
內存布局如下:
代碼二:
String str1 = "hello"; String str2 = new String("hello"); System.out.println(str1==str2); //打印結果為false
手動入池:
我們根據上圖知道了代碼二中的運行結果是false的,因為str2指向的是new String產生的String對象,而不是存儲“hello”的String對象的地址。如果寫為下面這個代碼,結果會是如何呢?
String str1 = "hello"; String str2 = new String("hello").intern(); System.out.println(str1==str2); //運行結果為true
為什么最后的結果為true呢?此時調用了String類當中的intern方法,稱為手動入池,它能夠將str2的指向不再指向new出來的String對象,而是指向了字符串常量池當中已經存儲有“hello”字符數組的String對象。
代碼三:
String str1 = "hello"; String str2 = "he"+"llo"; System.out.println(str1==str2); //打印結果為true
此代碼有關字符串的拼接。其實“he”與“llo”在編譯時期就已經編譯為“hello”了。如果要看編譯時期str2是什么字符串,則此時我們先點擊Build選項,點入Build Project選項則進行編譯(圖1)。可以在該類文件的路徑(含有.class文件)底下(圖2+圖3),按住shift鍵加右鍵點擊powershell窗口,輸入反編譯指令javap -c 類名
則能看到編譯時str2是否是已經拼接好的hello。
圖1:
圖2:在該類的窗口處點擊鼠標右鍵
圖三:退回上一個文件夾,點入out->prodection->字節碼文件所在的該文件夾名->按住shift點擊鼠標右鍵點入powershell窗口->輸入javap -c 類名
代碼四:
String str1 = "11"; String str2 = new String("1")+new String("1"); System.out.println(str1==str2); //運行結果為false
字符串的拼接會產生一個StringBuffer的類型,通過StringBuffer調用toString方法也轉變為String類,此時拼接完后字符串“11”存儲在value中,但是不會存儲到字符串常量池當中。
通過反編譯我們看到的確拼接產生StringBuffer,并且StringBuffer調用toString方法產生一個String類的對象存儲“11”。由圖1、圖2可以完全了解。
圖1:
圖2:
圖3:
對于字符串比較,我們不能直接用“==”,而有三種方法能夠對字符串有不同的比較方式。
比較字符串內容:直接調用String類的equals方法,將字符串放入括號當中比較。
比較字符串內容(不分字母大小寫):調用String類的equalsIgnoreCase方法。
String str1 = "hello" ; String str2 = "Hello" ; System.out.println(str1.equals(str2)); // false System.out.println(str1.equalsIgnoreCase(str2)); // true
比較字符串中的大小:調用String類當中的compareTo方法。本來String類當中是沒有compareTo方法,只不過String類實現了Comparable接口,并且重寫了compareTo方法。
它是一個字符一個字符進行比較的。如果str1大于str2則返回str1該字符減去str2該字符的值。例如:
代碼1:
String str1 = "abc"; String str2 = "bcd"; System.out.println(str1.compareTo(str2)); //運行結果為:-1
因為b的ASCII碼值比a的ASCII碼值大1,則直接返回-1。(如果是字符不相同則返回它們的ASCII碼差值)
代碼2:
String str1 = "bcdef"; String str2 = "bcd"; System.out.println(str1.compareTo(str2)); //運行結果為2
因為在str2比較結束前與str1的字符值是相同的。因此最后的結果是str1的長度減去str2的長度。
下面是String類的compareTo方法的實現。
1.判斷一個子串是否存在于主串中:調用String類的contains方法,返回值為boolean。
String str = "abbabcacc"; boolean flg = str.contains("abc"); System.out.println(flg); //打印結果為true
2.從頭開始查找一個子串,并返回第一個子串開始的索引位置,如果沒有,則返回-1。也可以傳入一個索引,代表是從哪個索引位置開始尋找,調用String類中的indexOf方法。
String str = "abbabcacc"; int index = str.indexOf("abc"); System.out.println(index); //打印結果為3
3.從尾處開始尋找,查看主串中有無傳入的子串,若有則返回索引值,沒有則返回-1。調用String類的lastIndexOf,并且也可以傳入索引代表從哪個索引值從尾處尋找到頭處。調用String類的lastIndexOf
代碼1:
String str = "abbabcacc"; int index = str.lastIndexOf("ac"); System.out.println(index); //打印結果為6
當我們要找的子串剛好被“切斷”時,它仍然會取到后面的字符返回子串開始的索引值,但是后面的字符的索引值不能取到。
代碼2:
String str = "abbabcacc"; int index = str.lastIndexOf("ac",6); System.out.println(index); //打印結果為6
4.判斷一個字符串是否以指定子串開頭,調用String類中的startsWith方法。也可以傳入索引值說明從指定位置開始判斷是否以指定子串開頭。
String str = "abbabcacc"; boolean flg = str.startsWith("abb"); System.out.println(flg); //打印結果為true String str = "abbabcacc"; boolean flg = str.startsWith("abb",3); System.out.println(flg); //打印結果為false
5.判斷一個字符串是否以指定子串結尾。調用String類當中的endsWith方法。
String str = "abbabcacc"; boolean flg = str.endsWith("acc"); System.out.println(flg); //打印結果為true
1.替換字符串中的所有的指定內容。調用String類當中的repalceAll方法。
String str = "helloworld" ; System.out.println(str.replaceAll("l", "_")); //打印結果為he__owor_d
也可以選擇替換字符串中的首個內容。調用String類中的repalceFirst方法。
System.out.println(str.replaceFirst("l", "_")); //打印結果為he_loworld
由于字符串是不可變對象, 替換不修改當前字符串, 而是產生一個新的字符串。
指定字符串在主串的基礎上能分為幾個組就等于分為幾個String類數組。因此可以通過foreach循環來遍歷拆分后的數組的內容。調用String類的split方法。
String str = "hello world hello bit" ; String[] result = str.split(" ") ; // 按照空格拆分 for(String s: result) { System.out.println(s); } //打印結果為
hello
world
hello
bit
split方法還能夠傳入一個limit參數,代表拆分后最多分為幾個數組。如果拆分后數組的個數小于這個limit值則按原來拆分的數組的個數拆分,否則數組的個數不能夠超過limit值
String str = "hello world hello bit" ; String[] result = str.split(" ",2) ; for(String s: result) { System.out.println(s); } //打印結果為
hello
world hello bit
當然,對于字符串的拆分可以嵌套拆分,即先拆分為兩部分,再根據另一個字符串再拆分。
String str = "name=zhangsan&age=18"; String[] strings = str.split("&"); for (String s:strings) { String[] ss = s.split("="); for (String s1:ss) { System.out.println(s1); } } //打印結果為
name
zhangsan
age
18
對于字符串的拆分還有幾種特殊情況,當遇到需要拆分的為轉義字符時,傳入指定的字符串則需要傳多兩個斜杠。例如:
String str = "192.168.1.1"; String[] strings = str.split("\\."); for (String s:strings) { System.out.println(s); } //打印結果為
192
168
1
1
因此需要注意的是:字符"|","*","+“都得加上轉義字符,前面加上”\\"。
對于字符串的拆分還可以根據多個指定的字符串進行拆分,指定的字符串之間用‘|'分隔。
String str = "Java30 12&21#hello"; String[] strings = str.split(" |&|#"); for (String s:strings) { System.out.println(s); } //打印結果為
Java30
12
21
hello
對于一個字符串的截取,傳入一個索引值代表是從哪個索引開始截取。傳入兩個索引值則代表截取的范圍。調用String類中的substring方法。例如:
String str = "helloworld" ; System.out.println(str.substring(5)); System.out.println(str.substring(0, 5)); //打印結果為
world
hello
注意:
索引從0開始
注意前閉后開區間的寫法, substring(0, 5) 表示包含 0 號下標的字符, 不包含 5 號下標
對于以上字符串操作的方法,我們可以查看其原碼能夠更好地了解該方法是如何進行操作的。
1.String類的trim方法。這個方法是用來去掉字符串中左右兩邊空格,而字符串中間的空格是不會去掉的。
代碼:
String str = " abc def "; String s = str.trim(); System.out.println(s); //打印結果為
abc def
2.String類中的toUpperCase和toLowerCase方法。toUpperCase是用來將字符串中的小寫字母轉變為大寫字母,而不是字母的不進行處理。toLowerCase方法是用來將字符串中的大寫字母轉變為寫寫字母,而不是字母的也不進行處理。
String str = " hello%$$%@#$%world 哈哈哈 " ; System.out.println(str.toUpperCase()); System.out.println(str.toLowerCase()); //打印結果為:
HELLO%$$%@#$%WORLD 哈哈哈
hello%$$%@#$%world 哈哈哈
3.String類中的concat方法。這個方法是用來連接字符串的,相當于字符串中的拼接,但是連接后的字符串不會入到字符串常量池當中。這里不再演示。
4.String類中的length方法。它是用來求字符串長度的,跟數組不一樣,數組中的length是數組的屬性,而String中的length是一個方法。
代碼:
String str = "abcd"; System.out.println(str.length()); //打印結果為4
5.String類中的isEmpty方法。是用來判斷字符串是否為空的。
代碼:
System.out.println("hello".isEmpty());//false System.out.println("".isEmpty());//true System.out.println(new String().isEmpty());//true
對上面String字符串常量池有了了解后,我們知道了String是常量,是不可變的。當拼接時,Java會在編譯期間將String類的對象拼接優化為StringBuffer的拼接(不會產生新對象),因此Java中有StringBuffer和StringBuilder中處理字符串,并且它們拼接時不會產生新的對象,而是在原來的字符串基礎上拼接。后面我們再將StringBuilder和StringBuffer的區別。
StringBuilder中有一個append方法可以將字符串在原來的基礎上拼接。例如當我們有這樣的代碼時:
String str = "abc"; for (int i = 0; i < 10; i++) { str+=i; } System.out.println(str); //打印結果:
abc0123456789
會在常量池中產生很多的臨時變量,例abc0會在字符串常量池中產生,abc01又會在字符串常量池中產生等等。如果我們用到StringBuilder的append方法時,可以寫為(兩種寫法最后的結果是相同的,只是StringBuilder處理時不會在字符串常量池中產生臨時變量):
StringBuilder stringBuilder = new StringBuilder("abc"); for (int i = 0; i < 10; i++) { stringBuilder.append(i); } System.out.println(stringBuilder); //打印結果:
abc0123456789
打印時為什么能夠打印StringBuilde類型是因為StringBuilder中重寫了父類的toString方法,它能夠把StringBuilder類型轉變為String類型進行打印。
append方法也可以連著使用。代碼如下:
public static void main(String[] args) { StringBuffer sb = new StringBuffer(); sb.append("Hello").append("World"); fun(sb); System.out.println(sb); } //打印結果為
HelloWorld
因此:
String變為StringBuffer:利用StringBuffer的構造方法或append()方法。
StringBuffer變為String:調用toString()方法。
StringBuilder與StringBuffer中的方法都是大致相同的。它們的主要區別就是StringBuilder主要是用于單線程的,而StringBuffer主要是用于多線程的。我們點入StringBuffer類當中按住ctrl+7選擇append方法看到如圖所示的synchronized英文,則代表是多線程使用的,而StringBuilder類中沒有。
結論:
String的內容不可修改,StringBuffer與StringBuilder的內容可以修改.
StringBuffer與StringBuilder大部分功能是相似的
StringBuffer采用同步處理,屬于線程安全操作;而StringBuilder未采用同步處理,屬于線程不安全操作
StringBuilder與StringBuffer常用的方法一般String類當中都是沒有的,例如:append方法、delete方法、reserve方法、insert方法等。
reverse方法:
StringBuffer sb = new StringBuffer("helloworld"); System.out.println(sb.reverse()); //打印結果為
dlrowolleh
delete方法:
StringBuffer sb = new StringBuffer("helloworld"); System.out.println(sb.delete(5, 10)); //打印結果為
hello
insert方法:
StringBuffer sb = new StringBuffer("helloworld"); System.out.println(sb.delete(5, 10).insert(0, "你好")); //打印結果為:
你好hello
許多人認為,如果傳一個引用到一個函數中指向了另一個對象,就能夠解決“所有問題”,其實不然,下面這個例子能夠說明問題。
代碼:
public static void func(String str1,char[] chars) { str1="hello"; chars[0]='g'; } public static void main(String[] args) { String str = "abcd"; char[] chars = {'h','e','l','l','o'}; func(str,chars); System.out.println(str); System.out.println(Arrays.toString(chars)); } //打印結果為
abcd
[g, e, l, l, o]
結果為什么str沒有指向hello而chars而又還是改變的是原來那個hello的基礎上變為gello呢?在我們學了字符串常量池后,了解到了字符串常量池只能存儲一個內容相同的字符串常量。因此,傳入func函數當中str1是一個形參,是str1指向了新的對象“hello”,但是main函數中的str指向的還是abcd。而chars是真真正正地在原來數組的基礎上0下標的字符改為了‘g',最后打印的結果為[g, e, l, l, o]是沒有任何問題的。
到此,關于“Java中String類的使用方法有哪些”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。