做者:泥沙磚瓦漿木匠 網站:http://blog.csdn.net/jeffli1993 我的簽名:打算起手不凡寫出鴻篇巨做的人,每每堅持不了完成第一章節。 |
提及String,你們最熟悉不過了。我也是那麼說過,可是彷彿這熟悉的裏面也有不少細節,或者是咱們沒掌握的東西。每每有不少舊東西里面爆出不少光點。好比,做者泥瓦匠近期在冬天的牛仔褲裏面搜出了一張100現金(不宜樂乎)。回到正題,咱們下面如下幾點講下String。分兩個部分:
基礎部分:(JDK源碼 文檔) 算法
擴展部分: api
樓主不是大牛級別的人物,泥瓦匠一直認爲的是「打算起手不凡寫出鴻篇巨做的人,每每堅持不了完成第一章節。」因此,操着鍵盤,聽着喜歡的音樂。幽默的對你說個人理解體會。
(但願大牛指出錯誤,萬分感謝!) 數組
懷着初次見你的心情,泥瓦匠和你一塊兒打開JDK1.7文檔。我最近想寫一些關於JDK1.7的理解,都知道JDK8出來了,新特性我準備下階段有空學習。
泥瓦匠想說,閱讀E文文檔有利於體會原汁原味。但畢竟國內大牛翻譯的很不錯了,我們不加評判,喜歡哪一種本身挑。能抓老鼠,能解決實際項目,適應業務環境的就是你學到了。請看下面的小例子: 網絡
清單1.1 app
String abc = "abc"; char data[] = {'a','b','c'}; String abcStr = new String(data); System.out.println("abc"); String cde = "cde"; System.out.println("abc" + cde); String c = "abc".substring(2,3); String d = cde.substring(1, 2); System.out.println(c); System.out.println(d);
泥瓦匠,你不是在忽悠我嗎?這麼簡單的程序,你想說什麼。說實在確實是基礎,但基礎紮實纔能有更高的突破。就想泥瓦匠默默爲本身,爲家人爲將來打基礎。 框架
能夠見,String是不須要用new來建立一個新對象的類。它是不可變的(Constant),其值(像"abc"建立後,不可改變)。天然,String其實實現了基本類型char的序列的功能,所以中文名「字符串」。這裏你們有可能疑惑,泥瓦匠就找到JDK源碼證據給大家看: ide
這段代碼是來自JDK1.7源碼裏面的,char型value數組的形式組成了String類的內容。其操做就是針對value數組操做。這樣想是否豁然開朗,而後內心自喜「so easy」。其實難點下面,你們慢慢看下去。 函數
依舊看代碼清單1.1,Java提供了一個特殊的鏈接操做符(concatenation operator)+ 用於直接來拼接字符串。其中操做經常使用的方法羅列以下: 學習
方法 做用
s.length() 返回s字符串長度 s.charAt(1) 返回s字符串中下標爲1的字符 s.substring(0, 2) 返回s字符串中下標0到2的子字符串 s.indexOf("nsg") 返回子字符串"nsg"的下標 s.startsWith(" ") 判斷s是否以空格開始 s.endsWith("end") 判斷s是否以"end"結束
跟着泥瓦匠運行下清單1.1,你能夠看到打印出來: 優化
abc abccde c d
有人看到這個會大吃一驚,而後質問說「老師說,String 和 == 不要緊,你是否是瞎扯淡」。哈哈,我只能說,只不過修行在實際。舉個小栗子吧。
看下面清單1.2
static String b = "ab"; private static void test(){ String a = "a" + "b"; System.out.println(a == b); }
看到這裏,你是否以爲這麼簡單,內心想着確定是「false,泥瓦匠真逗。」運行下,結果倒是
true
泥瓦匠的記憶宮殿:就是至關於 泥瓦匠和個人親姐姐比較咱們兩個的爸爸,畢竟的爸爸都是那一個,固然是true。
"a" + "b"的生命是怎麼樣的呢?網絡牛人有些反編譯會發現實際上是相似下面的過程:
StringBuilder temp = new StringBuilder(); temp.append("a").append("b"); return temp.toString();
究竟JVM是怎麼把"a" + "b"和"ab"知道他們是同樣的呢。咱們回顧下,由於String是不可變類,也就是靜態Java語言的特色。這涉及到JVM的優化方案。但JVM很死板,它不會很人工智能的像人腦,它會的只是它能處理的,因此好好了解JVM有助於開發更好的額程序。好比定義一個ab字符串常量夠了,它不會在再 子串 a b。這就是它的優化方案。
泥瓦匠的記憶宮殿:這就是偷懶思想,今天我要見我爸爸,明天姐姐要見爸爸。合併下唄,後天一塊兒去見爸爸。
就此咱們能夠得出結論:編譯器給我帶來它對程序的優化,爲了提高程序的效率和內存資源等,因此咱們能夠明白,如何掌握其特性寫出更好的代碼。
補充個例子,看看大家真的掌握沒?
private static String getA(){ return "a";} private static void test2(){ String a = "a"; String b = a + "b"; String e = getA() + "b"; System.out.println(b == "ab"); System.out.println(e == "ab"); }
false false
若是猜到了,證實你真懂了。泥瓦匠仍是耐心的講解下:
第一個false:b是包括了一個常量和一個引用的值,因此。
第二個false: 你也能夠猜到外部方法的常量在本方法只是一個引用。因此。
結論以下:咱們如今若是不知道JVM怎麼在編譯時期優化,咱們就慢慢了解它們。
這個例子很差寫,泥瓦匠就帶大家看看源碼等。equals並不陌生,相信你們的系統裏面有不少設計到這個方法。
其實equals是實現了Object的equals方法,而在Object的equals:
它其實就是實現了 == 比較內存的內容。
Q:泥瓦匠,爲何String要重寫Object,這不致使意義不一致了嗎?
A:非也非也,String是String,String用來處理的事物邏輯和業務和Object徹底不一樣。equals顧名思義等於,等於不表示徹底相等。而是同樣或者類似。正所謂業務看狀況,好比泥瓦匠處理得金融數據通常小數點10幾位,那請問你還會在意小數點10位後的的值嗎,當它們比較的時候,你不會在意,因此這就是類似。
簡單描述下,就是遍歷兩個數組最好的條件下,就是要麼長度不一樣,要麼前面幾個不一樣。直接返回false。
Q:若是碰到大字符串這就悲劇了。因此一些大字符串怎麼處理呢。
A:其實實際中,大字符串也難見。但說處理的話,大字符串匹配能夠考慮分割匹配或是啥的這裏就不展開了。
Q:equals重寫 和 hashCode 有關係嗎?
A:這裏咱們要先說明hashCode方法提供對象的hashCode值,返回與默認的System.identityHashCode()一致。其普遍用於集合框架。到後面我也會講到。hashCode的源於計算機的比較源於數字,而不是對象。因此一個hashCode值標識一個對象,產生了對象相關的不少算法。可是默認的hashCode犯法會發起對本地的調用開銷很大。
intern你們就有點陌生了。我們首先得普及下常量池的概念,常量池(constant pool)指的是在編譯期被肯定,並被保存在已編譯的.class文件中的一些數據。它包括了關於類、方法、接口等中的常量,也包括字符串常量。而後看看下面的例子:
private static void test5(){ String a = "a"; String b = a + "b"; String c = "ab"; String d = new String("ab"); System.out.println(c == d.intern()); System.out.println(b.intern() == d.intern()); }
當調用 intern()方法時,JVM 會在這個常量池中經過 equals()方法查找是否存在等值的 String,若是存在,則直接返回常量池中這個 String 對象的地址;沒有找到,則會建立等值的字符串,返回其地址。
思考提高:這有什麼用呢?
答曰:能夠用於一些常量的存儲比較,枚舉(枚舉底層就是字符串,哈哈)。當想常量比常量,多數的狀況下,考慮效率則選擇 intern()而不是equals。
String是Java基礎組件重要的一部分。我慢慢的總結的J2EE Java的組件體系,而後增長內容進去。仍是那句話,泥瓦匠想說:
如以上文章或連接對你有幫助的話,別忘了在文章按鈕或到頁面右下角點擊 「贊一個」 按鈕哦。你也能夠點擊頁面右邊「分享」懸浮按鈕哦,讓更多的人閱讀這篇文章