深入學(xué)習(xí)Java編程中的字符串的進(jìn)階使用
JAVA雖然是在C++基礎(chǔ)上發(fā)展而來(lái),但卻對(duì)C++的許多缺陷有所改進(jìn),其中一個(gè)不得不提的就是字符串,我們知道,隨著學(xué)習(xí)的深入,進(jìn)入MFC時(shí),當(dāng)處理字符串或字符時(shí),常會(huì)需要通過(guò)_T()宏將字符或字符串變成UNICODE型,否則,會(huì)在處理中出現(xiàn)BUG,而在JAVA中,字符char或存儲(chǔ)在Character類(lèi)中的字符,不是一個(gè)字節(jié),而是2個(gè)字節(jié),采用UNICODE,這是為了支持全世界上的所有字符。
字符的序列組成字符串,有兩種類(lèi)型的字符串:一種是創(chuàng)建以后不需要修改的,稱為字符串常量,在JAVA中,用String類(lèi)存儲(chǔ);
一種是創(chuàng)建以后需要對(duì)其進(jìn)行修改的,稱為字符串變量,在JAVA中,用StringBuffer類(lèi)操作和管理。
StringBuffer類(lèi)
1、創(chuàng)建StringBuffer類(lèi)對(duì)象
StringBuffer類(lèi)對(duì)象表示的是字符串變量(注意是"變量"),每一個(gè)StringBuffer類(lèi)對(duì)象都是可以擴(kuò)充和修改的字符串變量。以下是常用的StringBuffer類(lèi)構(gòu)造函數(shù):
(1)public StringBuffer()
創(chuàng)建一個(gè)新的空的StringBuffer類(lèi)的對(duì)象,其容量初值設(shè)置成16個(gè)字符(注意是16個(gè)字符)
(2)public StringBuffer(int length)
創(chuàng)建一個(gè)新的空的StringBuffer類(lèi)的對(duì)象,其容量初值設(shè)置成length個(gè)字符
(3)public StringBuffer(String str)
創(chuàng)建一個(gè)新的StringBuffer類(lèi)的對(duì)象,其內(nèi)容為str的內(nèi)容,容量設(shè)置成str長(zhǎng)度再加16個(gè)字符 (注意:再加上16個(gè)字符)
2、StringBuffer類(lèi)對(duì)象的常用方法
(1)StringBuffer類(lèi)對(duì)象的擴(kuò)充
StringBuffer類(lèi)提供兩組方法用來(lái)擴(kuò)充StringBuffer對(duì)象所包含的字符,分別是:
1)public StringBuffer append
(Object obj)
append方法用于擴(kuò)充StringBuffer對(duì)象所包含的字符,該方法將指定的參數(shù)對(duì)象轉(zhuǎn)化為字符串后,將其附加在原來(lái)的StringBuffer對(duì)象之后,并返回新的StringBuffer對(duì)象。附加的的參數(shù)對(duì)象可以是各種數(shù)據(jù)類(lèi)型的,如int、char、String、double等。
2)public StringBuffer insert(
int插入位置offset,參數(shù)對(duì)象類(lèi)型,參數(shù)對(duì)象名)
該方法將指定的參數(shù)對(duì)象轉(zhuǎn)化為字符串后,將其插入在原來(lái)的StringBuffer對(duì)象中指定的位置,并返回新的StringBuffer對(duì)象。
(2)StringBuffer類(lèi)對(duì)象的長(zhǎng)度與容量
一個(gè)StringBuffer類(lèi)對(duì)象的長(zhǎng)度指的是它包含的字符個(gè)數(shù);容量指的是被分配的字符空間的數(shù)量。
1)public int length()
該方法返回當(dāng)前StringBuffer類(lèi)對(duì)象包含的字符個(gè)數(shù)。
2)public int capacity()
該方法返回當(dāng)前StringBuffer類(lèi)對(duì)象分配的字符空間的數(shù)量。
(3)StringBuffer類(lèi)對(duì)象的修改
public void setCharAt(intindex,charch)
該方法將當(dāng)前StringBuffer對(duì)象中的index位置的字符替換為指定的字符ch。
(4)字符串的賦值和加法
字符串是在程序中要經(jīng)常使用的數(shù)據(jù)類(lèi)型,在Java編譯系統(tǒng)中引入了字符串的賦值和加法操作。
(5)其它方法類(lèi)似String類(lèi)的方法
3、利用StringTokenizer類(lèi)分解字符串
StringTokenizer類(lèi)位于java.util包中, 在使用該類(lèi)時(shí)在程序開(kāi)始加上
importjava.util.StringTokenizer或
importjava.util.*
StringTokenizer類(lèi)
對(duì)于StringTokenizer類(lèi),其主要作用是將字符串按照給定的分割符進(jìn)行分割,其功能和String類(lèi)的split方法類(lèi)似
1、StringTokenizer類(lèi)的構(gòu)造函數(shù)
(1)StringTokenizer(Stringstr)
為給定的字符串str創(chuàng)建一個(gè)StringTokenizer對(duì)象,其分隔符默認(rèn)設(shè)置為“\t\n\r\f”,亦即:空格、水平制表符tab、換行、回車(chē)、表格符
(2)StringTokenizer(String str,String delim)
為給定的字符串str創(chuàng)建一個(gè)StringTokenizer對(duì)象,其分隔符為指定的字符串delim,默認(rèn)不包含分隔符
3)StringTokenizer(String str,String delim,boolean returnDelims)
為給定的字符串str創(chuàng)建一個(gè)StringTokenizer對(duì)象,其分隔符為指定的字符串delim,如果returnDelims為true,則創(chuàng)建的StringTokenizer對(duì)象中的每個(gè)字符串包含有分隔符,否則不包含分隔符
2、StringTokenizer類(lèi)的常用方法
nIntcountTokens()
返回StringTokenizer對(duì)象中被分割后子字符串的個(gè)數(shù)
nBooleanhasMoreElements()
該方法的功能和hasMoreTokens()方法的功能一樣
nBooleanhasMoreTokens()
檢測(cè)StringTokenizer對(duì)象中是否包含分割好的子字符串,有則返回true,否則返回false
ObjectnextElement()
該方法具有nextToken()一樣的功能,主要區(qū)別是它返回的不是String對(duì)象,而是一個(gè)Object對(duì)象
StringnextToken()
返回StringTokenizer對(duì)象中下一個(gè)分割好的子字符串
StringnextToken(String delim)
返回StringTokenizer對(duì)象中下一個(gè)分割好的子字符串,但是分隔符被重新設(shè)定為delim
n其實(shí)在有些編程語(yǔ)言中,比如C語(yǔ)言,其字符串就是由字符數(shù)組構(gòu)成的,每個(gè)字符串的結(jié)尾用“\0”標(biāo)志,但是在Java中卻不是這樣的。
n在Java中,字符串通常是作為String類(lèi)的對(duì)象存在著,如:Strings=“I like Java!”,其中“Ilike Java!”就是一個(gè)對(duì)象。
所以說(shuō),Java中的字符串和字符數(shù)組是完全不相同的,和C語(yǔ)言中的字符串也是不一樣的!
n為了方便字符串和字符數(shù)組的轉(zhuǎn)換,在String類(lèi)中提供了許多這樣的構(gòu)造函數(shù)和方法
n如構(gòu)造函數(shù)String(char[] value)
n方法toCharArray()
方法valueOf(char[] data)
常量池
對(duì)于源程序中出現(xiàn)的字符串常量,當(dāng)程序運(yùn)行時(shí),會(huì)統(tǒng)一保存到一個(gè)常量池中進(jìn)行緩存。
對(duì)引用這些緩存在常量池中的字符串的變量進(jìn)行比較,用==也會(huì)得到正確的結(jié)果。
但在運(yùn)行時(shí),對(duì)字符串的各種操作如+、substring等等,都是會(huì)產(chǎn)生新的字符串對(duì)象的。
但是強(qiáng)大的編譯器會(huì)對(duì)字符串常量的拼接進(jìn)行優(yōu)化,諸如s3 = "hell" + "o"時(shí),s3仍然會(huì)
指向常量池中的字符串。但對(duì)于變量的運(yùn)算,總不能要求虛擬機(jī)執(zhí)行諸如s1 + s2時(shí)還要
判斷結(jié)果是否已在常量池中了吧。因此,要用equals而非==去判斷兩個(gè)字符串是否相等。
public static void main(String[] args) { // String constants are put in constant pool. String s1 = "hello"; String s2 = "hello"; String s3 = "hell" + "o"; System.out.println(s1 == s2); System.out.println(s1 == s3); // Operation like +,substring on string create new one. String s4 = "hell"; String s5 = s4 + "o"; System.out.println(s1 == s5); System.out.println(s1.equals(s5)); // substring has special handle on substring(0) String s6 = s1.substring(0); System.out.println(s1 == s6); }
測(cè)試代碼s1、s2、s3的字節(jié)碼:
0: ldc #16; //String hello
2: astore_1
3: ldc #16; //String hello
5: astore_2
6: ldc #16; //String hello
8: astore_3
測(cè)試代碼s4、s5的字節(jié)碼:
41: ldc #30; //String hell
43: astore 4
45: new #32; //class java/lang/StringBuilder
48: dup
49: aload 4
51: invokestatic #34; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
54: invokespecial #40; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
57: ldc #43; //String o
59: invokevirtual #45; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
62: invokevirtual #49; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
注意一點(diǎn)是substring方法,substring(0,3)是得到從字符0到2的字符串。這樣設(shè)計(jì)的原因
也許是這樣容易計(jì)算子串的長(zhǎng)度,3-0=3。同時(shí)substring對(duì)于特殊參數(shù)有特別的優(yōu)化處理:
public String substring(int beginIndex, int endIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } if (endIndex > count) { throw new StringIndexOutOfBoundsException(endIndex); } if (beginIndex > endIndex) { throw new StringIndexOutOfBoundsException(endIndex - beginIndex); } return ((beginIndex == 0) && (endIndex == count)) ? this : new String(offset + beginIndex, endIndex - beginIndex, value); }
由此看出,String對(duì)象背后并沒(méi)有什么神奇之處,對(duì)字節(jié)碼有了些了解可以更好的理解它。
其實(shí)常量池中還保存類(lèi)及其方法的很多信息,如包名、類(lèi)名、方法簽名等等,有興趣可以
深入研究。
- 零基礎(chǔ)寫(xiě)Java知乎爬蟲(chóng)之進(jìn)階篇
- Java進(jìn)階學(xué)習(xí):jar打包詳解
- Java 正則表達(dá)式入門(mén)詳解(基礎(chǔ)進(jìn)階)
- Java異常處理之try...catch...語(yǔ)句的使用進(jìn)階
- Java中jqGrid 學(xué)習(xí)筆記整理——進(jìn)階篇(二)
- Java進(jìn)階:JNI使用技巧點(diǎn)滴
- Java進(jìn)階教程之IO基礎(chǔ)
- Java進(jìn)階學(xué)習(xí):網(wǎng)絡(luò)服務(wù)器編程
- 老生常談Java字符串進(jìn)階(必看篇)
- 開(kāi)發(fā)10年,全記在這本Java進(jìn)階寶典里了
相關(guān)文章
深入了解Java中的過(guò)濾器Filter和監(jiān)聽(tīng)器Listener
這篇文章主要為大家詳細(xì)介紹了Java中的過(guò)濾器Filter和監(jiān)聽(tīng)器Listener的使用以及二者的區(qū)別,文中的示例代碼講解詳細(xì),需要的可以參考一下2022-06-06Java線程安全和鎖Synchronized知識(shí)點(diǎn)詳解
在本篇文章里小編給大家分享的是關(guān)于Java線程安全和鎖Synchronized相關(guān)知識(shí)點(diǎn),有需要的朋友們可以參考下。2019-08-08掌握SpringMVC中@InitBinder的實(shí)際應(yīng)用
這篇文章主要介紹了掌握SpringMVC中@InitBinder的實(shí)際應(yīng)用,@InitBinder是Spring MVC框架中的一個(gè)注解,用于自定義數(shù)據(jù)綁定的方法,通過(guò)在控制器中使用@InitBinder注解,可以將特定的數(shù)據(jù)綁定邏輯應(yīng)用于請(qǐng)求參數(shù)的處理過(guò)程中,需要的朋友可以參考下2023-10-10SpringBoot?AOP?Redis實(shí)現(xiàn)延時(shí)雙刪功能實(shí)戰(zhàn)
本文主要介紹了SpringBoot?AOP?Redis實(shí)現(xiàn)延時(shí)雙刪功能實(shí)戰(zhàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08SpringBoot URL帶有特殊字符([]/{}等),報(bào)400錯(cuò)誤的解決
這篇文章主要介紹了SpringBoot URL帶有特殊字符([]/{}等),報(bào)400錯(cuò)誤的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02Java封裝數(shù)組實(shí)現(xiàn)包含、搜索和刪除元素操作詳解
這篇文章主要介紹了Java封裝數(shù)組實(shí)現(xiàn)包含、搜索和刪除元素操作,結(jié)合實(shí)例形式分析了java針對(duì)數(shù)組元素的查找、刪除、判斷等相關(guān)操作封裝與使用技巧,需要的朋友可以參考下2020-03-03