一文帶你吃透Java中的String類(lèi)
Java語(yǔ)言中的String對(duì)象是一個(gè)非常常見(jiàn)的數(shù)據(jù)類(lèi)型,大多數(shù)情況下我們都是在使用String對(duì)象來(lái)表示字符串類(lèi)型的數(shù)據(jù)。Java中的String類(lèi)是一個(gè)final class,它是不可被繼承的。本文將對(duì)Java中的String對(duì)象進(jìn)行詳細(xì)全面的描述,包括以下幾個(gè)方面:
一、String類(lèi)的概述
在 Java 中,字符串是一種常見(jiàn)的數(shù)據(jù)類(lèi)型,經(jīng)常用于存儲(chǔ)一些文本信息。而String類(lèi)則是Java提供的專(zhuān)門(mén)用于字符串操作的類(lèi),在Java標(biāo)準(zhǔn)庫(kù)中,它位于java.lang包中。
String類(lèi)是不可被繼承的final類(lèi),即它不能被其他類(lèi)所繼承,也就是說(shuō)它不能被修改。String類(lèi)是通過(guò)使用Unicode字符集來(lái)表示字符串的,這使得Java支持多語(yǔ)言字符集。由于String類(lèi)的不可變性(immutable),所以它可以作為安全的參數(shù)發(fā)送給諸如網(wǎng)絡(luò)連接或數(shù)據(jù)庫(kù)鏈接之類(lèi)的方法,而不必?fù)?dān)心其被篡改。String對(duì)象可以用來(lái)存儲(chǔ)任何字符串類(lèi)型的數(shù)據(jù),包括HTML、XML等格式的字符串。
二、String類(lèi)的構(gòu)造函數(shù)
在 Java 中,String類(lèi)提供了多種構(gòu)造函數(shù),可以用于創(chuàng)建字符串對(duì)象。下面是String類(lèi)的一些常用構(gòu)造函數(shù):
- String(char[] value):根據(jù)字符數(shù)組value來(lái)創(chuàng)建String對(duì)象。
- String(char[] value, int offset, int count):根據(jù)字符數(shù)組value的指定部分(offset開(kāi)始的count個(gè)字符)來(lái)創(chuàng)建String對(duì)象。
- String(byte[] bytes):根據(jù)字節(jié)數(shù)組bytes來(lái)創(chuàng)建String對(duì)象,使用平臺(tái)默認(rèn)的字符集。
- String(byte[] bytes, Charset charset):根據(jù)字節(jié)數(shù)組bytes來(lái)創(chuàng)建String對(duì)象,使用指定的字符集charset。
- String(String original):根據(jù)原始字符串original來(lái)創(chuàng)建String對(duì)象。
例如:
String str1 = new String("Hello World!"); char[] charArray = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'}; String str2 = new String(charArray);
三、String類(lèi)的常用方法
在Java中,String類(lèi)還提供了很多常用的方法,下面我們來(lái)介紹一些常用的方法:
3.1、字符串拼接
String concat(String str):連接指定的字符串參數(shù)到此字符串的末尾。
例如:
String s1 = "Hello"; String s2 = "World"; String s3 = s1.concat(s2); // s3 = "HelloWorld"
3.2、字符串截取
- char charAt(int index):返回指定索引處的 char 值。
- int indexOf(int ch):返回指定字符在此字符串中第一次出現(xiàn)處的索引。
- int indexOf(int ch, int fromIndex):返回指定字符在此字符串中從指定位置后第一次出現(xiàn)處的索引。
- int indexOf(String str):返回指定子字符串在此字符串中第一次出現(xiàn)處的索引。
- int lastIndexOf(int ch):返回指定字符在此字符串中最后一次出現(xiàn)處的索引。
- int lastIndexOf(int ch, int fromIndex):返回指定字符在此字符串中從指定位置前最后一次出現(xiàn)處的索引。
- int lastIndexOf(String str):返回指定子字符串在此字符串中最后一次出現(xiàn)處的索引。
- String substring(int beginIndex):返回一個(gè)新的字符串,它是此字符串的一個(gè)子字符串。
- String substring(int beginIndex, int endIndex):返回一個(gè)新的字符串,它是此字符串的一個(gè)子字符串。
例如:
String str = "Java is the best programming language!"; System.out.println(str.charAt(5)); // out: 'i' System.out.println(str.indexOf("the")); // out: 8 System.out.println(str.substring(0, 4)); // out: "Java"
3.3、字符串替換
- String replace(char oldChar, char newChar):返回一個(gè)新的字符串,它是通過(guò)用 newChar 替換此字符串中出現(xiàn)的所有 oldChar 得到的。
- String replace(CharSequence target, CharSequence replacement):使用指定的 replacement 替換此字符串所有匹配給定的正則表達(dá)式的子字符串。
例如:
String str = "Java is the best programming language!"; System.out.println(str.replace('a', 'A')); // out: "JAvA is the best progrAmming lAnguAge!" System.out.println(str.replace("the", "a")); // out: "Java is a best programming language!"
3.4、字符串分割
- String[] split(String regex):根據(jù)指定的正則表達(dá)式拆分此字符串。
- String[] split(String regex, int limit):根據(jù)指定的正則表達(dá)式拆分此字符串,最多拆分出limit個(gè)子字符串。
例如:
String str = "Java is the best programming language!"; String[] words1 = str.split(" "); System.out.println(Arrays.toString(words1)); // out: ["Java", "is", "the", "best", "programming", "language!"] String[] words2 = str.split(" ", 3); System.out.println(Arrays.toString(words2)); // out: ["Java", "is", "the best programming language!"]
3.5、大小寫(xiě)轉(zhuǎn)換
- String toLowerCase():使用默認(rèn)語(yǔ)言環(huán)境的規(guī)則將此 String 所有字符都轉(zhuǎn)換為小寫(xiě)。
- String toUpperCase():使用默認(rèn)語(yǔ)言環(huán)境的規(guī)則將此 String 所有字符都轉(zhuǎn)換為大寫(xiě)。
例如:
String str = "Java is the best programming language!"; System.out.println(str.toUpperCase()); // out: "JAVA IS THE BEST PROGRAMMING LANGUAGE!"
3.6、字符串比較
- boolean equals(Object anObject):將此字符串與指定對(duì)象進(jìn)行比較。如果兩個(gè)對(duì)象相等,則返回 true;否則返回 false。
- boolean equalsIgnoreCase(String anotherString):將此 String 與另一個(gè) String 進(jìn)行比較,不考慮大小寫(xiě)。
- boolean startsWith(String prefix):測(cè)試此字符串是否以指定的前綴開(kāi)始。
- boolean endsWith(String suffix):測(cè)試此字符串是否以指定的后綴結(jié)束。
- int compareTo(String anotherString):按字典順序比較兩個(gè)字符串。
例如:
String str1 = "Java is awesome!"; String str2 = "Java is great!"; System.out.println(str1.equals(str2)); // out: false System.out.println(str1.startsWith("Java")); // out: true System.out.println(str2.endsWith("great!")); // out: true System.out.println(str1.compareTo(str2)); // out: -6
四、String類(lèi)的不可變性原理及優(yōu)缺點(diǎn)
String類(lèi)在Java中是不可變的(immutable)的,這意味著一旦創(chuàng)建了一個(gè)String對(duì)象,它的值就不能被修改。String類(lèi)的不可變性主要由以下兩個(gè)方面造成:
4.1、String類(lèi)的存儲(chǔ)結(jié)構(gòu)
在Java中,String對(duì)象實(shí)際上是一個(gè)包含字符數(shù)組的引用和一個(gè)表示字符串長(zhǎng)度的整數(shù)。因此,在進(jìn)行字符串操作時(shí),String對(duì)象的引用和長(zhǎng)度是不會(huì)變化的,只有字符數(shù)組才會(huì)被修改。而由于Java數(shù)組是一個(gè)固定長(zhǎng)度的數(shù)據(jù)結(jié)構(gòu),因此String對(duì)象的不可變性就被保證了。
4.2、String類(lèi)的操作方法
在Java中,String對(duì)象提供了很多用于字符串操作的方法(例如substring、concat等)。這些方法都是返回一個(gè)新的String對(duì)象,而不會(huì)在原有的String對(duì)象上進(jìn)行修改,這也保證了String對(duì)象的不可變性。
String對(duì)象的不可變性帶來(lái)了下面的優(yōu)點(diǎn):
- 線(xiàn)程安全:由于String對(duì)象的不可變性,多個(gè)線(xiàn)程可以對(duì)同一個(gè)String對(duì)象進(jìn)行訪(fǎng)問(wèn)操作,而不必?fù)?dān)心數(shù)據(jù)的安全問(wèn)題。
- 安全性:由于String對(duì)象不可變,它不能被篡改,從而可以避免一些惡意攻擊。
- 性能優(yōu)化:由于String對(duì)象是不可變的,因此可以進(jìn)行一些性能方面的優(yōu)化。例如,String類(lèi)實(shí)現(xiàn)了字符串池這個(gè)概念。
同時(shí)也存在以下缺點(diǎn):
- 內(nèi)存占用:由于每次使用String類(lèi)進(jìn)行字符串操作時(shí),都會(huì)創(chuàng)建一個(gè)新的String對(duì)象,并且原有的String對(duì)象不會(huì)被修改,這樣就會(huì)占用更多的內(nèi)存空間。
- 創(chuàng)建大量垃圾對(duì)象:由于String對(duì)象的不可變性,每進(jìn)行一次字符串操作就會(huì)創(chuàng)建一個(gè)新的String對(duì)象,如果進(jìn)行大量的字符串操作,就會(huì)創(chuàng)建大量的垃圾對(duì)象,導(dǎo)致垃圾回收器的頻繁運(yùn)行。
- 字符串拼接效率低:由于每進(jìn)行一次字符串拼接操作,就會(huì)創(chuàng)建一個(gè)新的String對(duì)象,效率較低。
五、String類(lèi)的實(shí)現(xiàn)原理及性能問(wèn)題
在 Java 中,String對(duì)象是通過(guò)char[]字符數(shù)組來(lái)存儲(chǔ)字符串的。StringBuilder和StringBuffer也是通過(guò)char[]數(shù)組來(lái)存儲(chǔ)字符串的,只不過(guò)它們?cè)谶M(jìn)行字符串操作時(shí),會(huì)在原有的char[]數(shù)組上進(jìn)行修改,而不是每次都創(chuàng)建一個(gè)新的char[]數(shù)組。
由于String對(duì)象的不可變性,每次對(duì)String對(duì)象進(jìn)行字符串操作時(shí)都會(huì)創(chuàng)建一個(gè)新的String對(duì)象,這樣會(huì)導(dǎo)致大量的內(nèi)存開(kāi)銷(xiāo)和垃圾對(duì)象的產(chǎn)生,因此在進(jìn)行大量的字符串操作時(shí),應(yīng)該盡量使用StringBuilder或StringBuffer來(lái)避免這些問(wèn)題。
StringBuilder和StringBuffer都繼承了AbstractStringBuilder類(lèi),它們之間的區(qū)別在于StringBuilder是線(xiàn)程不安全的,而StringBuffer是線(xiàn)程安全的。如果多個(gè)線(xiàn)程需要對(duì)同一個(gè)字符串進(jìn)行操作時(shí),應(yīng)該使用StringBuffer來(lái)保證線(xiàn)程安全性。
在進(jìn)行字符串操作時(shí),如果需要?jiǎng)?chuàng)建一個(gè)新的String對(duì)象,可以使用靜態(tài)方法String.valueOf()或者直接將字符數(shù)組傳遞給String類(lèi)的構(gòu)造函數(shù)來(lái)創(chuàng)建新的String對(duì)象,這樣可以避免產(chǎn)生大量的垃圾對(duì)象。
六、字符串池的工作原理
Java中有一種稱(chēng)為字符串池(String Pool)的機(jī)制,它的主要作用是避免創(chuàng)建重復(fù)的String對(duì)象,從而節(jié)省內(nèi)存空間。
當(dāng)創(chuàng)建一個(gè)字符串時(shí),JVM首先會(huì)在字符串池中查找該字符串是否已經(jīng)存在。如果存在,則返回該字符串在字符串池中的引用;否則,在字符串池中創(chuàng)建該字符串,并返回該字符串在字符串池中的引用。
下面是一個(gè)示例代碼:
String str1 = "Hello"; String str2 = "Hello"; String str3 = new String("Hello"); System.out.println(str1 == str2); // true,因?yàn)閟tr1和str2都指向字符串池中的同一個(gè)對(duì)象 System.out.println(str1 == str3); // false,因?yàn)閟tr3指向堆內(nèi)存中新創(chuàng)建的String對(duì)象
因此,如果需要?jiǎng)?chuàng)建多個(gè)相同的字符串對(duì)象,可以直接使用字符串池中已有的對(duì)象,這樣可以節(jié)省內(nèi)存空間。
七、String類(lèi)與StringBuilder、StringBuffer的比較
在進(jìn)行字符串操作時(shí),Java中常用的有String、StringBuilder和StringBuffer三種類(lèi)。
- String:String類(lèi)是不可變的,每次進(jìn)行字符串操作時(shí)都會(huì)創(chuàng)建一個(gè)新的String對(duì)象。因此,在需要大量字符串操作時(shí),使用String類(lèi)效率較低。
- StringBuilder:StringBuilder是可變的,它可以在原有的字符數(shù)組上進(jìn)行修改,而不用每次都創(chuàng)建一個(gè)新的字符數(shù)組。因此,在需要大量字符串操作時(shí),使用StringBuilder類(lèi)可以提高效率。
- StringBuffer:StringBuffer也是可變的,并且是線(xiàn)程安全的,因此適用于多個(gè)線(xiàn)程對(duì)同一字符串進(jìn)行操作的場(chǎng)景。
下面是一個(gè)比較字符串拼接效率的示例代碼:
String s = ""; for (int i = 0; i < 10000; i++) { s += "a"; }
上述代碼中使用了String來(lái)進(jìn)行字符串拼接操作,每次都會(huì)創(chuàng)建一個(gè)新的String對(duì)象,因此效率較低。下面是使用StringBuilder進(jìn)行字符串拼接的代碼示例:
StringBuilder sb = new StringBuilder(); for (int i = 0; i < 10000; i++) { sb.append("a"); } String s = sb.toString();
由于StringBuilder是可變的,因此在進(jìn)行字符串操作時(shí)效率較高。
總之,在進(jìn)行大量的字符串操作時(shí),應(yīng)該盡量使用StringBuilder或StringBuffer,避免使用String類(lèi)導(dǎo)致效率低下。
以上就是一文帶你吃透Java中的String類(lèi)的詳細(xì)內(nèi)容,更多關(guān)于Java String類(lèi)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java在文件尾部追加內(nèi)容的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇java在文件尾部追加內(nèi)容的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12Java引用類(lèi)型interface的用法總結(jié)
這篇文章主要為大家詳細(xì)介紹了Java中引用類(lèi)型interface的用法的相關(guān)資料,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定幫助,感興趣的可以了解一下2022-10-10MyBatis-Plus攔截器對(duì)敏感數(shù)據(jù)實(shí)現(xiàn)加密
做課程項(xiàng)目petstore時(shí)遇到需要加密屬性的問(wèn)題,而MyBatis-Plus為開(kāi)發(fā)者提供了攔截器的相關(guān)接口,本文主要介紹通過(guò)MyBatis-Plus的攔截器接口自定義一個(gè)攔截器類(lèi)實(shí)現(xiàn)敏感數(shù)據(jù)如用戶(hù)密碼的加密功能,感興趣的可以了解一下2021-11-11linux的shell命令檢測(cè)某個(gè)java程序是否執(zhí)行
ps -ef |grep java|grep2016-04-04SpringBoot根據(jù)目錄結(jié)構(gòu)自動(dòng)配置Url前綴方式
這篇文章主要介紹了SpringBoot根據(jù)目錄結(jié)構(gòu)自動(dòng)配置Url前綴方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11java使用java.io.File類(lèi)和java.nio.file.Path類(lèi)對(duì)文件重命名
這篇文章主要給大家介紹了關(guān)于java使用java.io.File類(lèi)和java.nio.file.Path類(lèi)對(duì)文件重命名的相關(guān)資料,本文僅為日常操作記錄,方便后期使用查找本地電腦文件太多了,又不想一個(gè)一個(gè)重命名,改名字什么的很麻煩,需要的朋友可以參考下2024-02-02SpringBoot的@Value注解如何設(shè)置默認(rèn)值
這篇文章主要介紹了SpringBoot的@Value注解如何設(shè)置默認(rèn)值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02mybatis group by substr函數(shù)傳參報(bào)錯(cuò)的解決
這篇文章主要介紹了mybatis group by substr函數(shù)傳參報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01