我們?cè)賮砜匆欢未a:

運(yùn)行一下:

沒錯(cuò),一個(gè)true,一個(gè)是false,(答錯(cuò)的小朋友去面壁去),大家可能在想編譯器肯定又調(diào)皮了,編譯的時(shí)候是不是又偷偷加了些什么,迫不及待的打開class文件看一下:
除了刪掉了空行以外和我的java源文件一致呀,這回可冤枉編譯器了,那為什么會(huì)導(dǎo)致不同的結(jié)果呢?我們都知道,Java代碼是運(yùn)行在JVM里的,那是不是JVM在執(zhí)行這段代碼時(shí)給我們做了什么?
在JVM中,當(dāng)代碼執(zhí)行到String s1 = "100" 時(shí),會(huì)先看常量池里有沒有字符串剛好是“100”這個(gè)對(duì)象,如果沒有,在常量池里創(chuàng)建初始化該對(duì)象,并把引用指向它,如下圖,綠色部分為常量池,存在于堆內(nèi)存中。

當(dāng)執(zhí)行到String s2 = "100" 時(shí),發(fā)現(xiàn)常量池已經(jīng)有了100這個(gè)值,于是不再在常量池中創(chuàng)建這個(gè)對(duì)象,而是把引用直接指向了該對(duì)象,如下圖:

這時(shí)候我們打印System.out.println(s1 == s2)時(shí),由于==是判斷兩個(gè)對(duì)象是否指向同一個(gè)引用,所以這兒打印出來的就應(yīng)該是true。
繼續(xù)執(zhí)行到Strings3 = new String("100") 這時(shí)候我們加了一個(gè)new關(guān)鍵字,這個(gè)關(guān)鍵字呢就是告訴JVM,你直接在堆內(nèi)存里給我開辟一塊新的內(nèi)存,如下圖所示:

繼續(xù)執(zhí)行String s4 = new String("100")

這時(shí)候再打印System.out.println(s3 == s4) 那一定便是false了,因?yàn)閟3和s4不是指向?qū)σ粋€(gè)引用(對(duì)象)。
注:圖中只是畫出了main方法棧和相關(guān)對(duì)象在內(nèi)存中的大致模擬,實(shí)際中JVM中內(nèi)存管理比較復(fù)雜,大家有條件的話可以去找《Java虛擬機(jī)規(guī)范》這本書去深入研究。
結(jié)論:我們?cè)诒容^兩個(gè)String對(duì)象內(nèi)容時(shí),無論是怎么聲明的,都一定要使用equals去比較,不能用==,在Java中沒有重載操作符這一說,特別是從其它語言轉(zhuǎn)到Java的童鞋們要注意。equals我在其它文章里已經(jīng)做了詳細(xì)解說,傳送門:說說Java里的equals(上)- Java那些事兒

如果喜歡本系列文章,請(qǐng)為我點(diǎn)贊或順手分享,您的支持是我繼續(xù)下去的動(dòng)力,您也可以在評(píng)論區(qū)留言想了解的內(nèi)容,有機(jī)會(huì)本專欄會(huì)做講解,最后別忘了關(guān)注一下我。
轉(zhuǎn)載無限歡迎,但請(qǐng)注明「作者」和「原文地址」。轉(zhuǎn)載請(qǐng)?jiān)谖闹斜A舸硕?,感謝您對(duì)作者版權(quán)的尊重。