在編寫(xiě)程序的過(guò)程中河咽,不了避免的要用到字符串寺庄,所以String類(lèi)的常用方法的用法是必須掌握的俐巴。學(xué)習(xí)一個(gè)類(lèi)的使用方法最好的措施就是讀JAVA類(lèi)庫(kù)
的官方文檔和閱讀源碼耀石。jdk1.8 api谷歌翻譯中文版下載地址
- String類(lèi)的基本概述
- 從文檔中可以知道String類(lèi)屬于java.lang包牵囤,所以使用時(shí)不用導(dǎo)包,String用final修飾滞伟,故不能有子類(lèi)揭鳞,繼承了Object類(lèi),實(shí)現(xiàn)了接口Serializable梆奈,Comparable<String>野崇,CharSequence
- String類(lèi)代表字符串。 Java程序中的所有字符串文字(例如"abc" )都被實(shí)現(xiàn)為此類(lèi)的實(shí)例亩钟。字符串不變; 它們的值在創(chuàng)建后不能被更改乓梨。 字符串緩沖區(qū)支持可變字符串鳖轰。 因?yàn)镾tring對(duì)象是不可變的,它們可以被共享扶镀。即String str = "abc"蕴侣,"abc"就是String的一個(gè)對(duì)象。而且"abc"不能改變臭觉,即使對(duì)str再次賦值str = "def"昆雀,也只是將str指向新的字符串,原來(lái)的字符串"abc"任然沒(méi)有改變蝠筑,并且變成了內(nèi)存中的垃圾狞膘。
- 字符串常量被放在內(nèi)存的常量池中。當(dāng)創(chuàng)建一個(gè)字符串常量后什乙,系統(tǒng)會(huì)在常量池中查找是否有與該字符串常量字面值相同的字符串挽封,如果沒(méi)有,就在常量池中創(chuàng)建該常量臣镣。
- Java語(yǔ)言為字符串連接運(yùn)算符(+)提供特殊支持场仲,并為其他對(duì)象轉(zhuǎn)換為字符串。 字符串連接是通過(guò)StringBuilder (或StringBuffer )類(lèi)及其append方法實(shí)現(xiàn)的退疫。 字符串轉(zhuǎn)換是通過(guò)方法toString來(lái)實(shí)現(xiàn)渠缕。如""+'a'+10將空串""與后面的字符a和整型10相連將變成"a10"。在介紹了后面的String的構(gòu)造方法后將對(duì)這一機(jī)制的實(shí)現(xiàn)做進(jìn)一步的描述褒繁。
- 構(gòu)造方法
- 字符串常量直接賦值
String str = "abc";
String str2 = "abc";
System.out.println(str == str2);
輸出結(jié)果是true亦鳞。正如概述中所說(shuō),通過(guò)這種方式賦值給字符串變量(引用類(lèi)型)棒坏,字符串常量的字面值就是該變量的實(shí)例對(duì)象燕差。在常量池中創(chuàng)建了"abc"后,對(duì)于語(yǔ)句2坝冕,發(fā)現(xiàn)"abc"已經(jīng)在常量池中存在了徒探,所以就將該"abc"也賦給了str2,所以str和str2指向的是同一個(gè)對(duì)象喂窟,地址值是相同的测暗。這一過(guò)程的內(nèi)存分配如圖。
- 空參構(gòu)造
String()初始化新創(chuàng)建的String對(duì)象磨澡,使其表示空字符序列碗啄。 - 有參構(gòu)造
String(String original)
初始化新創(chuàng)建的String對(duì)象,使其表示與參數(shù)相同的字符序列;換句話(huà)說(shuō)稳摄,新創(chuàng)建的字符串是參數(shù)字符串的副本稚字。String s1 = new String("abc");
這個(gè)語(yǔ)句是在常量池中創(chuàng)建了常量"abc",然后在堆內(nèi)存中創(chuàng)建了一個(gè)字符串對(duì)象,將"abc"的值拷貝到這個(gè)對(duì)象中胆描。所以實(shí)際上是常見(jiàn)了兩個(gè)對(duì)象瘫想,并且將堆內(nèi)存的對(duì)象的地址賦給s1。這一過(guò)程的內(nèi)存圖如下昌讲。
String(byte[] bytes)
通過(guò)使用平臺(tái)的默認(rèn)字符集解碼指定的字節(jié)數(shù)組來(lái)構(gòu)造新的String国夜。通過(guò)這個(gè)方法可以將數(shù)組轉(zhuǎn)換成字符串。
byte[] arr = {97,98,99};
String str3 = new String(arr);
System.out.println(str3); //abc
將字符數(shù)組組成字符串剧蚣,使用的編碼是由平臺(tái)的編碼系統(tǒng)決定的支竹。不同于字符的編碼旋廷,java的字符編碼是固定的unicode鸠按,而組成字符串是將硬盤(pán)中的字節(jié)數(shù)據(jù)轉(zhuǎn)到內(nèi)存中,將這些字節(jié)流進(jìn)行編碼饶碘,使之成為我們能夠理解的語(yǔ)言目尖,又成為字節(jié)流的解碼過(guò)程,這個(gè)涉及到輸入輸出流的問(wèn)題扎运。在以后學(xué)習(xí)后再進(jìn)一步闡述瑟曲。String(byte[] bytes, int offset, int length)
這個(gè)構(gòu)造方法可以選擇從byte數(shù)組中的哪個(gè)字節(jié)開(kāi)始,取幾個(gè)字節(jié)構(gòu)成字符串豪治。
byte[] arr2 = {97,98,99,100};
String str4 = new String(arr2, 1, 3);
System.out.println(str4); //bcd
其實(shí)通過(guò)源碼可以看到洞拨,將整個(gè)數(shù)組轉(zhuǎn)化成字符串的構(gòu)造方法底層的實(shí)現(xiàn)其實(shí)就是這個(gè)有參構(gòu)造方法,只是對(duì)其進(jìn)行了封裝负拟,使我們的使用更加方便了烦衣。
public String(byte bytes[]) {
this(bytes, 0, bytes.length);
}
Sting (char[] value,int offset,int count)
將指定的字符數(shù)組從offset開(kāi)始,長(zhǎng)度為count的字符元素連綴成字符串掩浙。
char[] arr = {'a','b','c'};
String str = new String(arr,1,2);
System.out.println(str); //bc
以上便是常用的構(gòu)造方法花吟,對(duì)于這一部分,通過(guò)一個(gè)小練習(xí)來(lái)加深對(duì)字符串概念的理解厨姚。
String str = "ab";
String str2 = "abc";
String str3 = str +"c";
System.out.println(str2 == str3); //false
System.out.println(str2.equals(str3)); //true
前兩條語(yǔ)句很好理解衅澈,就是在常量池中創(chuàng)建字符串常量"ab"和"abc"并將他們的地址賦給str和str2,對(duì)于第三條語(yǔ)句谬墙,就是字符串特有的用過(guò)+將字符串與其他數(shù)據(jù)類(lèi)型拼接成新的字符串今布。先創(chuàng)建了一個(gè)StringBuffer對(duì)象,將字符串的值進(jìn)行拼接拭抬,在通過(guò)toString方法將StringBuffer轉(zhuǎn)化成String险耀,再將新的String對(duì)象的地址賦給str3,所以str2和str3的地址值是不一樣玖喘,str2對(duì)象地址在常量池甩牺,而str3對(duì)象地址在堆。內(nèi)存圖如圖所示累奈。
- 常用方法
- char charAt(int index):獲取字符串中指定位置的字符贬派。字符串的索引與數(shù)組的類(lèi)似急但,都是從0開(kāi)始的。這個(gè)方法常用來(lái)遍歷字符串中的元素搞乏。
- int length():返回字符串的長(zhǎng)度
上面兩個(gè)方法常常用來(lái)遍歷字符串的元素
String str = "abcd";
for (int i = 0;i<str.length();i++){
System.out.print(str.charAt(i)+" "); //a b c d
}
- boolean equals(String str);判斷兩個(gè)字符串是否相等
- boolean equalsIngnoreCase(String str):不區(qū)分大小寫(xiě)判斷兩個(gè)字符是否相等
- boolean startWith(String prefix)判斷字符串是否以prefix開(kāi)始
- boolean starWith(String prefix , int toffset)判斷字符串從toffset位置算起波桩,是否以prefix開(kāi)始
- boolean endWith(String suffix):判斷字符串是否以suffix結(jié)尾
- boolean contain(CharSequence s)判斷字符串是否包含子串s
以上方法的測(cè)試代碼
String str = "abc";
String str2 = "Abc";
String str3 = "ab";
String str4 = "bc";
System.out.println(str.equals(str2)); //false
System.out.println(str.equalsIgnoreCase(str2));//true 不區(qū)分大小寫(xiě)
System.out.println(str.startsWith(str3)); //true
System.out.println(str.endsWith(str4)); //true
System.out.println(str.contains(str3)); //true
- boolean isEmpty()判斷字符串是否為空,注意字符串為空串请敦,和字符串引用為空的區(qū)別
String str5 = "";
String str6 = null;
System.out.println(str5.isEmpty()+" "+str.isEmpty());//true false
System.out.println(str6.isEmpty()); //NullPointerException字符串為空不等于空指針
當(dāng)字符串指針指向?yàn)榭諘r(shí)镐躲,相當(dāng)于沒(méi)有指向?qū)ο螅荒軐?duì)其調(diào)用任何方法侍筛,否則會(huì)出現(xiàn)空指針異常
- int indexOf(String str) 返回str子字符串在該字符串中第一次出現(xiàn)的位置
- int indexOf(String str,int fromIndex) 返回str子字符串在該字符串中從fromIndex開(kāi)始后第一次出現(xiàn)的位置
- int indexOf(char ch) 返回ch字符在該字符串中從fromIndex開(kāi)始扣第一次出現(xiàn)的位置
- int index(char ch,int fromIndex)返回字符在該字符串中從fromIndex開(kāi)始后第一次出現(xiàn)的位置
- int lastIndexOf(String str, int fromIndex)返回從fromIndex開(kāi)始向前找子字符串str在該字符中第一次出現(xiàn)的位置
- String substring(int beginIndex, int endIndex)截取從beginIndex開(kāi)始到endIndex結(jié)束的子串萤皂,注意的是這個(gè)包含頭不包含尾,即不包含索引endIndex處的字符
關(guān)于返回字符串索引的位置的方法代碼練習(xí)
public class Demo_String4 {
public static void main(String[] args) {
demo1();
demo2();
demo3();
demo4();
}
private static void demo4() {
String str = "abcd";
System.out.println(str.substring(2, 4));//cd,從指定位置截取字符串到指定位置結(jié)束,包含頭不包含尾
}
private static void demo3() {
String str = "abcde";
System.out.println(str.indexOf("cd", 1)); // 2,,從指定位置往后找
System.out.println(str.lastIndexOf("bc",4)); //1,從指定位置向前找
}
private static void demo2() {
String str = "abcd";
int x = str.indexOf('b'); //參數(shù)是int,傳入字符會(huì)自動(dòng)類(lèi)型提升
int y = str.indexOf("cd");
System.out.println(x); //1
System.out.println(y); //2
System.out.println(str.indexOf("be"));//-1
}
private static void demo1() {
char[] chararry= {'a','b','c'};
String str = "abc";
String str2 = "中文字符串";
System.out.println(chararry.length); //數(shù)組的length是屬性
System.out.println(str.length()+"..."+str2.length()); //字符串的length是方法,獲取的是字符的個(gè)數(shù),與字符字節(jié)數(shù)無(wú)關(guān)
System.out.println(str.charAt(2)); //c
System.out.println(str.charAt(3)); //StringIndexOutOfBoundsException字符串指針越界異常
}
}
- byte[] getBytes() 將字符串轉(zhuǎn)化成字節(jié)數(shù)組匣椰,這個(gè)過(guò)程又成為編碼過(guò)程裆熙,將人們理解的語(yǔ)言轉(zhuǎn)化成計(jì)算機(jī)識(shí)別的語(yǔ)言
String str = "abcd";
byte[] arr = str.getBytes(); //編碼:將字符轉(zhuǎn)換成計(jì)算機(jī)能識(shí)別的語(yǔ)言
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
String str2 = "中文字符串";
byte[] arr2 = str2.getBytes();
for (int i = 0; i < arr2.length; i++) {
System.out.print(arr2[i]+" "); //-42 -48 -50 -60 -41 -42 -73 -5 -76 -82
//gbk編碼,一個(gè)中文兩個(gè)字節(jié)禽笑,第一個(gè)必為負(fù)數(shù)
}
對(duì)于gbk編碼入录,一個(gè)中文由兩個(gè)字節(jié)組成,所以一個(gè)中文對(duì)應(yīng)數(shù)組中的兩個(gè)元素佳镜,且第一個(gè)元素必定為負(fù)數(shù)僚稿。
- char[] toCharArray()將字符串轉(zhuǎn)化成字符數(shù)組,一個(gè)字符對(duì)應(yīng)一個(gè)元素蟀伸,且這些字符都是由unicode編碼的
- static String valueOf(char data[])將字符數(shù)組轉(zhuǎn)化成字符串蚀同,前面提到一個(gè)將字符數(shù)組轉(zhuǎn)化成字符串的構(gòu)造方法,其實(shí)從源碼上看望蜡,這個(gè)方法就是通過(guò)這個(gè)構(gòu)造方法實(shí)現(xiàn)的唤崭,只不過(guò)將其封裝起來(lái),就不需要開(kāi)發(fā)者自己去調(diào)用這個(gè)構(gòu)造方法脖律,這個(gè)看似簡(jiǎn)單的方法谢肾,其實(shí)進(jìn)一步反映了對(duì)面對(duì)象的思想,就是盡量交由底層去實(shí)現(xiàn)小泉,使用者不需自己去實(shí)現(xiàn)芦疏,只負(fù)責(zé)通過(guò)對(duì)象調(diào)用這個(gè)方法就行了。
通過(guò)一個(gè)題目了解關(guān)于鏈?zhǔn)骄幊?br> 將一個(gè)字符串的首字母大寫(xiě)微姊,其余變成小寫(xiě)
public static void main(String[] args) {
String str2 = "zheSHiYIgecesHi";
System.out.println(str2.substring(0, 1).toUpperCase().concat(str2.substring(1).toLowerCase()));
}
代碼中只通過(guò)一行代碼就實(shí)現(xiàn)了酸茴,通過(guò)不斷掉調(diào)用對(duì)象的方法實(shí)現(xiàn)。只要一個(gè)方法返回的是一個(gè)對(duì)象兢交,就能不斷的調(diào)用其方法薪捍,稱(chēng)之為鏈?zhǔn)骄幊獭?/p>
- String replace(char oldChar, char newChar)將字符串中oldChar替換為newChar,如果原字符串中不存在oldChar字符,則不進(jìn)行修改
- int compareTo(String anotherString)比較兩個(gè)字符串的大小酪穿。如果兩個(gè)字符串的字符序列相等凳干,則返回0;不相等時(shí)被济,從兩個(gè)字符第0個(gè)字符開(kāi)始比較救赐,返回第一個(gè)不相等的字符差。另一種情況只磷,較長(zhǎng)字符串的前面部分恰好是較短額字符串经磅,則返回他們的長(zhǎng)度差。
- String trim()去除字符串兩端的空格钮追,常用語(yǔ)賬號(hào)密碼的讀取预厌,因?yàn)閮啥说目崭袢庋垭y以看見(jiàn),如果在錄入賬號(hào)密碼時(shí)不去除畏陕,常常會(huì)產(chǎn)生錯(cuò)誤配乓。
public static void main(String[] arg){
String str = "abcd";
System.out.println(str.replace('a', 'z'));
System.out.println(str.replace('c', 'z'));
System.out.println(str.compareTo("abc"));
String str2 = " abc ";
System.out.println(str2.trim()); //去除兩端空格,應(yīng)用:錄入賬號(hào)密碼兩端空格難以識(shí)別
System.out.println('中'+0); //unicode碼表
System.out.println('文'+0); //字符串與字節(jié)的轉(zhuǎn)換是系統(tǒng)的碼表,從內(nèi)存到硬盤(pán)的編碼
}
以上就是關(guān)于String類(lèi)的常用方法仿滔。
今天的學(xué)習(xí)的一個(gè)比較重要的體會(huì)是關(guān)于面向?qū)ο蟮乃枷氲膽?yīng)用惠毁。由于之前一直在用C語(yǔ)言,習(xí)慣性的采用面對(duì)過(guò)程的方法崎页,即很多都自己去實(shí)現(xiàn)每一個(gè)步驟鞠绰,而今天發(fā)現(xiàn)很多簡(jiǎn)單的步驟,如調(diào)用另一個(gè)方法飒焦,在java中都是采取封裝成一個(gè)新的方法的形式蜈膨,這樣使用者就真正的做到,幾乎只需要?jiǎng)?chuàng)建對(duì)象牺荠,在使用對(duì)象的方法就行了翁巍,而不用總是通過(guò)底層的原理實(shí)現(xiàn)。第二是關(guān)于字節(jié)流休雌,漸漸區(qū)分了字節(jié)流與字符的區(qū)別灶壶,字符是一種數(shù)據(jù)類(lèi)型,而字節(jié)流失一連串的字節(jié)數(shù)據(jù)杈曲,即一串01數(shù)據(jù)驰凛,通過(guò)不同的編碼可以表示不同的數(shù)據(jù),包括數(shù)字担扑,符號(hào)恰响,甚至是其他的視頻,圖像的數(shù)據(jù)涌献。而字節(jié)流的單位通常是自己胚宦,即byte,所以getByte方法有稱(chēng)為編碼過(guò)程,就是將數(shù)據(jù)轉(zhuǎn)成01數(shù)據(jù)枢劝,以字節(jié)為單位存放在數(shù)組中绞灼。