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