Java基礎(chǔ)之String類竭沫,StringBuffer類,StringBuilder類

一骑篙、String類蜕提,StringBuffer類,StringBuilder類


字符串類


String類靶端,StringBuffer類谎势,StringBuilder類都是Java中表示字符串的類,底層數(shù)據(jù)是char型的字符數(shù)組杨名。三個類都被final修飾脏榆,表示不可再被繼承。

String類是不可變的台谍,創(chuàng)建一個字符串對象之后须喂,對象的字符序列就不能被改變,因為String的成員char型數(shù)組是被定義為private final的趁蕊。

String類被設(shè)計為不可變的原因:

1)安全性:并發(fā)場景下坞生,由于String不能被改變,所以不會存在寫競爭的問題掷伙,任何線程讀到的都是同樣的字符串是己。另外一個安全是比如在類加載器加載類時,不可變類名保證了類被正確加載任柜。

2)String的hashCode是根據(jù)字符串內(nèi)容來的卒废,不可變保證了hashCode的不變性寒波,對于hashMap等容器,不可變的String類使其比其他對象更適合當(dāng)容器的鍵值升熊。

3)性能:String類型不可變時俄烁,字符串常量池才有意義,字符串常量池的出現(xiàn)级野,可以減少創(chuàng)建相同字面量的字符串页屠,讓不同的引用指向池中同一個字符串,為運(yùn)行時節(jié)約很多的堆內(nèi)存蓖柔。

StringBuilder和StringBuffer相似辰企,創(chuàng)建一個字符串對象之后是可以改變,他們的父類AbstractStringBuilder中成員char型數(shù)組沒有被定義為final况鸣,而且還提供一系列append方法和insert方法牢贸,將append或insert的東西加入到對象的char型數(shù)組。兩者的區(qū)別在于StringBuffer是線程安全的镐捧,因為此類中的絕大多數(shù)方法都是用synchronized修飾的潜索。

三、詳細(xì)了解String類

String類的常用方法

1.構(gòu)造方法

String s1 = new String(); // 定義一個空字符串""

String s2 = new String("hello"); //?聲明并初始化為"hello"字符串

char[] ch =new char[]{'h','e','l','l','o'}; String s3 =new String(ch);// 字符數(shù)組

byte[] b =new byte[]{1,3,4}; String s4 =new String(b);// byte數(shù)組

int[] i =new int[]{2,4,5,6}; String s5 =new String(i,0,3);// int數(shù)組

2.其他方法

int length() // 字符串長度

boolean isEmpty() // 是否為空字符串懂酱,即字符串長度是否為0

char charAt(int index) // 某位置上的字符竹习,從0開始。會拋StringIndexOutOfBoundsException

byte[] getBytes()列牺、byte[] getBytes(Charset charset)整陌、byte[] getBytes(String charsetName) // 轉(zhuǎn)換成字節(jié)數(shù)組,可傳指定字符集或字符集名字瞎领,字符集名字非法會拋UnsupportedEncodingException

boolean equals(Object anObject) // 比較此字符串是否和另一個對象相等泌辫,先用==比較是否是同一個對象,再看anObject是否是String的實例九默,再看兩字符串長度是否相等震放,再比較每一個字符是否相同

boolean equalsIgnoreCase(String anotherString) // 忽略大小寫比較兩個字符串是否相同

int compareTo(String anotherString) // 比較此字符串和anotherString的大小(每個字符的Unicode編碼)荤西,當(dāng)前字符串大于anotherString返回正數(shù)澜搅,等于返回0,小于返回負(fù)數(shù)

int compareToIgnoreCase(String str) // 同上邪锌,只是不區(qū)分字符的大小寫

boolean startsWith(String prefix)勉躺、boolean startsWith(String prefix,int toffset)、boolean endsWith(String suffix) // 以某字符串開頭或以某字符串結(jié)尾

int hashCode() // 字符串的hash碼觅丰,h=s[0] * 31^(n-1) + s[1] * 31^(n-2) + ... + s[n-1] (n為字符串長度)饵溅,選擇31的原因是:1)31是一個素數(shù),與素數(shù)相乘的方式更容易產(chǎn)生唯一性妇萄;2)如果是更大的素數(shù)蜕企,乘出來的結(jié)果可能會溢出咬荷,因為結(jié)果是int類型;3)31 * i 在計算時可為 (i<<5)- i

int indexOf(int ch)轻掩、int indexOf(int ch,int fromIndex)幸乒、int lastIndexOf(int ch)、int lastIndexOf(int ch,int fromIndex) // 字符第一次出現(xiàn)的位置或字符最后一次出現(xiàn)的位置唇牧,參數(shù)int類型的ch是字符的Unicode code point

int indexOf(String str)罕扎、int indexOf(String str,int fromIndex)、int lastIndexOf(String str)丐重、int lastIndexOf(String str,int fromIndex) // 字符串第一次出現(xiàn)的位置或最后一次出現(xiàn)的位置

String substring(int beginIndex) // 從beginIndex開始的子字符串腔召,包括beginIndex的位置,比如"hello".subString(2)返回從第二個位置開始的字串"llo"扮惦。

String substring(int beginIndex,int endIndex) //?從beginIndex開始到endIndex的子字符串,包括beginIndex的位置臀蛛,不包括endIndex的位置

String concat(String str) // 連接2個字符串 str1.concat(str2) 產(chǎn)生一個新的字符串,str1崖蜜、str2不變

boolean contains(CharSequence s) // 判斷一個字符串里是否包含某字符序列

String replace(char oldChar,char newChar) // 用新字符取代字符串中原來的字符浊仆,如 "hello".replace('e', 'i')返回"hillo",返回的"hillo"是一個新字符串纳猪,原來的"hello"不變

String replaceFirst(String regex, String replacement) // 將字符串中第一個匹配到regex字符串替換為replacement氧卧,產(chǎn)生一個新字符串桃笙,原字符串不變氏堤,"hellohe".replace("he","uo") 返回uollohe

String replaceAll(String regex, String replacement) // 將字符串中全部匹配到regex字符串替換為replacement,產(chǎn)生一個新字符串搏明,原字符串不變鼠锈,"hellohe".replace("he","uo") 返回uollouo

String replace(CharSequence target, CharSequence replacement) // 將字符串中target字符序列全部替換為

replacement字符序列,產(chǎn)生一個新字符串星著,原字符串不變购笆,"hellohe".replace("he","uo") 返回uollouo

replace與replaceAll的區(qū)別是:replace支持字符和字符串的替換,而repalceAll支持正則表達(dá)式替換虚循。

String[] split(String regex,int limit) // 用給定字符串作為分隔同欠,打斷字符串,返回字符串?dāng)?shù)組横缔,例子:

原字符串:str = "boo:and:foo"

str.split(":", 2); //?"boo", "and:foo"

str.split(":", 5); // "boo", "and", "foo"

str.split(":", -2); //?"boo", "and", "foo"

str.split("o", 5); // "b", "", ":and:f", "", ""

str.split("o", -2); //?"b", "", ":and:f", "", ""

str.split("o", 0); //?"b", "", ":and:f"

String[] split(String regex) // 同上铺遂,只是limit固定為0

static String join(CharSequence delimiter, CharSequence... elements) //字符串拼接,String.join("-", "Java", "is", "cool") 為"Java-is-cool"

static String join(CharSequence delimiter,Iterable elements) // 字符串拼接茎刚,List<String>strings = new LinkedList<>();strings.add("Java");strings.add("is"); strings.add("cool");String message = String.join(" ", strings); 結(jié)果為Java is cool

String toLowerCase() // 轉(zhuǎn)為小寫襟锐,生成新字符串

String toUpperCase() // 轉(zhuǎn)為大寫,生成新字符串

String trim() // 去掉字符串2端的空格

static String format(String format, Object... args) // 格式化膛锭,類似printf

3.本地方法

String類中唯一的一個本地方法:native String intern();?

由此方法引出常量池的概念粮坞,在Java中為了使程序運(yùn)行的更快蚊荣,更節(jié)省內(nèi)存,為8種基本類型及字符串常量引入了常量池莫杈,常量池類似Java系統(tǒng)級別提供的緩存互例。

對于字符串常量池,在JDK6及之前筝闹,存儲在永久代(PermGen Space)即方法區(qū)中敲霍,在JDK7及之后,字符串常量池被移到了堆中丁存,因為Perm區(qū)空間有限肩杈,如果程序中大量調(diào)用intern方法的話會產(chǎn)生java.lang.OutOfMemoryError:PermGen sapce錯誤。

對于直接使用雙引號聲明出的字符串解寝,會直接放入字符串常量池中扩然,如String s = "abc";

對于其他的String對象,調(diào)用intern方法也會被放入字符串常量池中聋伦,因為intern方法會先檢查常量池中是否有此字符串(有此字符串的含義是equals方法比較相等的字符串)夫偶,如果沒有,就將其放入到字符串常量池并返回其引用觉增。

一個例子:

String s1 = new StringBuilder("計算機(jī)").append("軟件").toString();

s1.intern() == s1;

JDK6為false兵拢;JDK7為true

解釋:JDK6中,new一個String對象時逾礁,在堆中創(chuàng)建了一個對象说铃,s1指向堆內(nèi)存中的地址,調(diào)s1.intern()方法時會先檢查常量池中是否有"計算機(jī)軟件"此字符串嘹履,發(fā)現(xiàn)沒有腻扇,于是在常量池中創(chuàng)建一個對象,并返回此對象的引用砾嫉,堆中的地址跟永久代中的地址肯定不一樣幼苛,所以結(jié)果為false;JDK7中焕刮,也是在堆中創(chuàng)建一個對象舶沿,s1指向堆內(nèi)存中的地址,當(dāng)調(diào)s1.intern()方法時配并,先檢查常量池中是否有"計算機(jī)軟件"此字符串括荡,因為此時字符串常量池就在堆中,所以認(rèn)為常量池中已有此字符串荐绝,于是返回了堆中的引用一汽,所以結(jié)果為true。

此例子為深入理解java虛擬機(jī)上的例子,更常見的例子見各博客召夹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末岩喷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子监憎,更是在濱河造成了極大的恐慌纱意,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鲸阔,死亡現(xiàn)場離奇詭異偷霉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)褐筛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進(jìn)店門类少,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人渔扎,你說我怎么就攤上這事硫狞。” “怎么了晃痴?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵残吩,是天一觀的道長。 經(jīng)常有香客問我倘核,道長泣侮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任紧唱,我火速辦了婚禮活尊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘琼蚯。我一直安慰自己酬凳,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布遭庶。 她就那樣靜靜地躺著,像睡著了一般稠屠。 火紅的嫁衣襯著肌膚如雪峦睡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天权埠,我揣著相機(jī)與錄音榨了,去河邊找鬼。 笑死攘蔽,一個胖子當(dāng)著我的面吹牛龙屉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼转捕,長吁一口氣:“原來是場噩夢啊……” “哼作岖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起五芝,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤痘儡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后枢步,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沉删,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年醉途,在試婚紗的時候發(fā)現(xiàn)自己被綠了矾瑰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡隘擎,死狀恐怖脯倚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嵌屎,我是刑警寧澤推正,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站宝惰,受9級特大地震影響植榕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜尼夺,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一尊残、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧淤堵,春花似錦寝衫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扎阶,卻和暖如春汹胃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背东臀。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工着饥, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惰赋。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓宰掉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子轨奄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,922評論 2 361

推薦閱讀更多精彩內(nèi)容