第二章 一切都是對象

盡管Java是基于C++的,但是相比之下,Java是更純粹的面向?qū)ο蟪绦蛟O(shè)計語言。

Java語言盡管將一切都視為對象,但實際上操控著程序的是對象的一個引用(reference)吕粗。可以將這種情形想象成遙控器(引用)控制著電視機(對象)巴帮。如果沒有電視機溯泣,遙控器也可單獨存在,即可能存在不指向任何對象的引用榕茧,如果意圖使用空引用進行任何操作垃沦,都會觸發(fā)空指針異常錯誤(java.lang.NullPointerException)。因此一種安全的做法是創(chuàng)建引用時便進行初始化用押,比如 :

String s = "當(dāng)時只道是尋常"

更通用的初始化方法通常是使用new關(guān)鍵字來關(guān)聯(lián)一個新對象肢簿。

String s = new String("當(dāng)時只道是尋常")

String對象是Java語言中重要的數(shù)據(jù)類型,但它并不是Java的基本數(shù)據(jù)類型蜻拨。雖然有兩種初始化方式池充,然而過程卻不一樣。


舉個栗子
String str1 = new String("ABC");
String str2 = new String("ABC");
str1 == str2    //false

String str1 = “ABC”;可能創(chuàng)建一個或者不創(chuàng)建對象缎讼,如果”ABC”這個字符串在java String池里不存在收夸,會在java String池里創(chuàng)建一個創(chuàng)建一個String對象(“ABC”),然后str1指向這個內(nèi)存地址血崭,無論以后用這種方式創(chuàng)建多少個值為”ABC”的字符串對象卧惜,始終只有一個內(nèi)存地址被分配厘灼,之后的都是String的拷貝,Java中稱為“字符串駐留”咽瓷,所有的字符串常量都會在編譯之后自動地駐留设凹。

String str3 = "ABC";
String str4 = "ABC";
String str5 =  "AB" + "C";
str3 == str4       //true
str3 == str5      // true

String str2 = new String(“ABC”);至少創(chuàng)建一個對象,也可能兩個茅姜。因為用到new關(guān)鍵字闪朱,肯定會在heap中創(chuàng)建一個str2的String對象,它的value是“ABC”钻洒。同時如果這個字符串在java String池里不存在奋姿,會在java池里創(chuàng)建這個String對象“ABC”

String a  = "ABC";
String b = "AB";
String c = b + "C";
a == c    //false

a航唆、b在編譯時就已經(jīng)被確定了胀蛮,而c是引用變量,不會在編譯時就被確定糯钙。

這就涉及到了Java中String對象的不可變性,什么叫不可變性呢退腥,簡單的說就是一旦一個String對象被創(chuàng)建并被賦值(初始化)這個對象的值就不會變化任岸。

一旦一個String對象在內(nèi)存中創(chuàng)建,它將是不可改變的狡刘,所有的String類中方法并不是改變String對象自己享潜,而是重新創(chuàng)建一個新的String對象。

建議在平時的使用中嗅蔬,盡量使用String = “abcd”;這種方式來創(chuàng)建字符串剑按,而不是String = new String(“abcd”);這種形式,因為使用new構(gòu)造器創(chuàng)建字符串對象一定會開辟一個新的heap空間澜术,而雙引號則是采用了String interning(字符串駐留)進行了優(yōu)化艺蝴,效率比構(gòu)造器高。

關(guān)于更多String對象的特性鸟废,請移步 http://book.51cto.com/art/201504/472207.htm

程序運行時猜敢,創(chuàng)建的對象和指向?qū)ο蟮囊檬侨绾芜M行存儲的?內(nèi)存又是如何分配的盒延?

  1. 寄存器(register)缩擂。這是最快的存儲區(qū),因為它位于不同于其他存儲區(qū)的地方——處理器內(nèi)部添寺。但是寄存器的數(shù)量極其有限胯盯,所以寄存器由編譯器根據(jù)需求進行分配。你不能直接控制计露,也不能在程序中感覺到寄存器存在的任何跡象博脑。

  2. 堆棧(stack)楞捂。位于通用RAM中,但通過它的“堆棧指針”可以從處理器那里獲得支持趋厉。堆棧指針若向下移動寨闹,則分配新的內(nèi)存;若向上移動君账,則釋放那些內(nèi)存繁堡。這是一種快速有效的分配存儲方法,僅次于寄存器乡数。創(chuàng)建程序時候椭蹄,JAVA編譯器必須知道存儲在堆棧內(nèi)所有數(shù)據(jù)的確切大小和生命周期,因為它必須生成相應(yīng)的代碼净赴,以便上下移動堆棧指針绳矩。這一約束限制了程序的靈活性,所以雖然某些JAVA數(shù)據(jù)存儲在堆棧中——特別是對象引用玖翅,但是JAVA對象不存儲其中翼馆。

  3. 堆(heap)。一種通用性的內(nèi)存池(也存在于RAM中)金度,用于存放所有的JAVA對象应媚。堆不同于堆棧的好處是:編譯器不需要知道要從堆里分配多少存儲區(qū)域,也不必知道存儲的數(shù)據(jù)在堆里存活多長時間猜极。因此中姜,在堆里分配存儲有很大的靈活性。當(dāng)你需要創(chuàng)建一個對象的時候跟伏,只需要new寫一行簡單的代碼丢胚,當(dāng)執(zhí)行這行代碼時,會自動在堆里進行存儲分配受扳。當(dāng)然携龟,為這種靈活性必須要付出相應(yīng)的代價。用堆進行存儲分配和清理可能比用堆棧進行存儲分配需要更多的時間辞色。

  4. 靜態(tài)存儲(static storage)骨宠。這里的“靜態(tài)”是指“在固定的位置”。靜態(tài)存儲里存放程序運行時一直存在的數(shù)據(jù)相满。你可用關(guān)鍵字static來標(biāo)識一個對象的特定元素是靜態(tài)的层亿,但JAVA對象本身從來不會存放在靜態(tài)存儲空間里。

  5. 常量存儲(constant storage)立美。常量值通常直接存放在程序代碼內(nèi)部匿又,這樣做是安全的,因為它們永遠不會被改變建蹄。有時碌更,在嵌入式系統(tǒng)中裕偿,常量本身會和其他部分分割離開,所以在這種情況下痛单,可以選擇將其放在ROM中嘿棘。

  6. 非RAM存儲。若數(shù)據(jù)完全獨立于一個程序之外旭绒,則程序不運行時仍可存在鸟妙,并在程序的控制范圍之外。其中兩個最主要的例子便是“流式對象”和“固定對象”挥吵。對于流式對象重父,對象會變成字節(jié)流,通常會發(fā)給另一臺機器忽匈。而對于固定對象房午,對象保存在磁盤中。即使程序中止運行丹允,它們?nèi)钥杀3肿约旱臓顟B(tài)不變郭厌。對于這些類型的數(shù)據(jù)存儲,一個特別有用的技巧就是它們能存在于其他媒體中嫌松。一旦需要沪曙,甚至能將它們恢復(fù)成普通的、基于RAM的對象萎羔。Java 1.1提供了對Lightweight persistence的支持。未來的版本甚至可能提供更完整的方案碳默。

對象引用存儲在堆棧(stack)中贾陷,對象存儲于堆(heap)中,上面談到的Java String池存儲在常量存儲區(qū)嘱根,常量存儲區(qū)也是方法區(qū)的一部分髓废。 了解更多Java虛擬機 運行時數(shù)據(jù)區(qū)

以上。


參考

《Java編程思想》
http://book.51cto.com/art/201504/472207.htm (作者:葛一鳴|來源:電子工業(yè)出版社)
https://www.cnblogs.com/mayj/p/7093526.html
http://www.cnblogs.com/Cratical/archive/2012/08/21/2649985.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末该抒,一起剝皮案震驚了整個濱河市慌洪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凑保,老刑警劉巖冈爹,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異欧引,居然都是意外死亡频伤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門芝此,熙熙樓的掌柜王于貴愁眉苦臉地迎上來憋肖,“玉大人因痛,你說我怎么就攤上這事“陡” “怎么了鸵膏?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長怎炊。 經(jīng)常有香客問我谭企,道長,這世上最難降的妖魔是什么结胀? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任赞咙,我火速辦了婚禮,結(jié)果婚禮上糟港,老公的妹妹穿的比我還像新娘攀操。我一直安慰自己,他們只是感情好秸抚,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布速和。 她就那樣靜靜地躺著,像睡著了一般剥汤。 火紅的嫁衣襯著肌膚如雪颠放。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天吭敢,我揣著相機與錄音碰凶,去河邊找鬼。 笑死鹿驼,一個胖子當(dāng)著我的面吹牛欲低,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播畜晰,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼砾莱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了凄鼻?” 一聲冷哼從身側(cè)響起腊瑟,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎块蚌,沒想到半個月后闰非,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡匈子,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年河胎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虎敦。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡游岳,死狀恐怖政敢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情胚迫,我是刑警寧澤喷户,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站访锻,受9級特大地震影響褪尝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜期犬,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一河哑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧龟虎,春花似錦璃谨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至棉安,卻和暖如春底扳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背贡耽。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工衷模, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蒲赂。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓算芯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親凳宙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

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

  • 如果我們說另一種不同的語言职祷,我們會發(fā)現(xiàn)另一個不同的世界 2.1 用引用來操作對象 每個語言都有自己操縱內(nèi)存元素的方...
    WandaGao閱讀 284評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理氏涩,服務(wù)發(fā)現(xiàn),斷路器有梆,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • Java 中幾乎一切都是對象是尖。 2.1 用引用操縱對象 對象(這里理解為變量)可以怎樣操縱? 直接操縱泥耀。 間接操縱...
    遺訓(xùn)餘風(fēng)閱讀 306評論 0 0
  • 向后兼容(Backward Compatbility)和向前兼容(Forward Compability)區(qū)別: ...
    浩林Leon閱讀 93評論 0 1
  • 2017總結(jié) 元旦3天迎瞧,花了3天的總共12個小時,看完了2017的每日總結(jié)逸吵,周總結(jié)凶硅。紙上短短的一句話就會讓自己回憶...
    同叔練級之路閱讀 1,032評論 0 97