5 個(gè)刁鉆的 String 面試題绵患!你都遇到過哪些雾叭?

1.判定定義為String類型的st1和st2是否相等,為什么

package string;

public class Demo2_String {

  public static void main(String[] args) {
    String st1 = "abc";
    String st2 = "abc";
    System.out.println(st1 == st2);
    System.out.println(st1.equals(st2));
  }

}

輸出結(jié)果:

第一行:true

第二行:true

分析:

先看第一個(gè)打印語句落蝙,在Java中==這個(gè)符號(hào)是比較運(yùn)算符织狐,它可以基本數(shù)據(jù)類型和引用數(shù)據(jù)類型是否相等,如果是基本數(shù)據(jù)類型筏勒,==比較的是值是否相等移迫,如果是引用數(shù)據(jù)類型,==比較的是兩個(gè)對(duì)象的內(nèi)存地址是否相等管行。

字符串不屬于8中基本數(shù)據(jù)類型起意,字符串對(duì)象屬于引用數(shù)據(jù)類型,在上面把“abc”同時(shí)賦值給了st1和st2兩個(gè)字符串對(duì)象病瞳,指向的都是同一個(gè)地址揽咕,所以第一個(gè)打印語句中的==比較輸出結(jié)果是 true

然后我們看第二個(gè)打印語句中的equals的比較,我們知道套菜,equals是Object這個(gè)父類的方法亲善,在String類中重寫了這個(gè)equals方法。

在JDK API 1.6文檔中找到String類下的equals方法逗柴,點(diǎn)擊進(jìn)去可以看大這么一句話“將此字符串與指定的對(duì)象比較蛹头。當(dāng)且僅當(dāng)該參數(shù)不為null,并且是與此對(duì)象表示相同字符序列的String 對(duì)象時(shí)戏溺,結(jié)果才為 true渣蜗。” 注意這個(gè)相同字符序列旷祸,在后面介紹的比較兩個(gè)數(shù)組耕拷,列表,字典是否相等托享,都是這個(gè)邏輯去寫代碼實(shí)現(xiàn)骚烧。

由于st1和st2的值都是“abc”浸赫,兩者指向同一個(gè)對(duì)象,當(dāng)前字符序列相同赃绊,所以第二行打印結(jié)果也為true既峡。

下面我們來畫一個(gè)內(nèi)存圖來表示上面的代碼,看起來更加有說服力碧查。

file

內(nèi)存過程大致如下:

1)運(yùn)行先編譯运敢,然后當(dāng)前類Demo2_String.class文件加載進(jìn)入內(nèi)存的方法區(qū)

2)第二步,main方法壓入棧內(nèi)存

3)常量池創(chuàng)建一個(gè)“abc”對(duì)象忠售,產(chǎn)生一個(gè)內(nèi)存地址

4)然后把“abc”內(nèi)存地址賦值給main方法里的成員變量st1传惠,這個(gè)時(shí)候st1根據(jù)內(nèi)存地址,指向了常量池中的“abc”档痪。

5)前面一篇提到,常量池有這個(gè)特點(diǎn)邢滑,如果發(fā)現(xiàn)已經(jīng)存在腐螟,就不在創(chuàng)建重復(fù)的對(duì)象

6)運(yùn)行到代碼 Stringst2 =”abc”, 由于常量池存在“abc”,所以不會(huì)再創(chuàng)建困后,直接把“abc”內(nèi)存地址賦值給了st2

7)最后st1和st2都指向了內(nèi)存中同一個(gè)地址乐纸,所以兩者是完全相同的。

2. 下面這句話在內(nèi)存中創(chuàng)建了幾個(gè)對(duì)象

String st1 = new String(“abc”);

答案是:在內(nèi)存中創(chuàng)建兩個(gè)對(duì)象摇予,一個(gè)在堆內(nèi)存汽绢,一個(gè)在常量池,堆內(nèi)存對(duì)象是常量池對(duì)象的一個(gè)拷貝副本侧戴。 另外宁昭,關(guān)注微信公眾號(hào):Java技術(shù)棧,在后臺(tái)回復(fù):面試酗宋,可以獲取我整理的 N 篇最新 Java 面試題整理积仗,都是干貨。

分析:

我們下面直接來一個(gè)內(nèi)存圖蜕猫。

file

當(dāng)我們看到了new這個(gè)關(guān)鍵字寂曹,就要想到,new出來的對(duì)象都是存儲(chǔ)在堆內(nèi)存回右。然后我們來解釋堆中對(duì)象為什么是常量池的對(duì)象的拷貝副本隆圆。

“abc”屬于字符串,字符串屬于常量翔烁,所以應(yīng)該在常量池中創(chuàng)建渺氧,所以第一個(gè)創(chuàng)建的對(duì)象就是在常量池里的“abc”。

第二個(gè)對(duì)象在堆內(nèi)存為啥是一個(gè)拷貝的副本呢蹬屹,這個(gè)就需要在JDK API 1.6找到String(String original)這個(gè)構(gòu)造方法的注釋:初始化一個(gè)新創(chuàng)建的 String 對(duì)象阶女,使其表示一個(gè)與參數(shù)相同的字符序列颊糜;換句話說,新創(chuàng)建的字符串是該參數(shù)字符串的副本秃踩。

所以衬鱼,答案就出來了,兩個(gè)對(duì)象憔杨。

3鸟赫、判定以下定義為String類型的st1和st2是否相等

package string;
public class Demo2_String {
   public static void main(String[] args) {
     String st1 = new String("abc");
     String st2 = "abc";
     System.out.println(st1 == st2);
     System.out.println(st1.equals(st2));
   }
}

答案:false 和 true

由于有前面兩道提內(nèi)存分析的經(jīng)驗(yàn)和理論,所以消别,我能快速得出上面的答案抛蚤。

==比較的st1和st2對(duì)象的內(nèi)存地址,由于st1指向的是堆內(nèi)存的地址寻狂,st2看到“abc”已經(jīng)在常量池存在岁经,就不會(huì)再新建,所以st2指向了常量池的內(nèi)存地址蛇券,所以==判斷結(jié)果輸出false缀壤,兩者不相等。

第二個(gè)equals比較纠亚,比較是兩個(gè)字符串序列是否相等塘慕,由于就一個(gè)“abc”,所以完全相等蒂胞。

內(nèi)存圖如下

file

4. 判定以下定義為String類型的st1和st2是否相等

package string;
 
public class Demo2_String {
 
   public static void main(String[] args) {
     String st1 = "a" + "b" + "c";
     String st2 = "abc";
     System.out.println(st1 == st2);
     System.out.println(st1.equals(st2));
   }
}

答案是:true 和 true

分析:

“a”,”b”,”c”三個(gè)本來就是字符串常量图呢,進(jìn)行+符號(hào)拼接之后變成了“abc”,“abc”本身就是字符串常量(Java中有常量優(yōu)化機(jī)制)骗随,所以常量池立馬會(huì)創(chuàng)建一個(gè)“abc”的字符串常量對(duì)象蛤织,在進(jìn)行st2=”abc”,這個(gè)時(shí)候,常量池存在“abc”鸿染,所以不再創(chuàng)建瞳筏。所以,不管比較內(nèi)存地址還是比較字符串序列牡昆,都相等姚炕。

5、判斷以下st2和st3是否相等

package string;
 
public class Demo2_String {
 
   public static void main(String[] args) {
     String st1 = "ab";
     String st2 = "abc";
     String st3 = st1 + "c";
     System.out.println(st2 == st3);
     System.out.println(st2.equals(st3));
   }
}

答案:false 和 true

分析:

上面的答案第一個(gè)是false丢烘,第二個(gè)是true柱宦,第二個(gè)是true我們很好理解,因?yàn)楸容^一個(gè)是“abc”播瞳,另外一個(gè)是拼接得到的“abc”掸刊,所以equals比較,這個(gè)是輸出true赢乓,我們很好理解忧侧。

那么第一個(gè)判斷為什么是false石窑,我們很疑惑。同樣蚓炬,下面我們用API的注釋說明和內(nèi)存圖來解釋這個(gè)為什么不相等松逊。

首先,打開JDK API 1.6中String的介紹肯夏,找到下面圖片這句話经宏。

file

關(guān)鍵點(diǎn)就在紅圈這句話,我們知道任何數(shù)據(jù)和字符串進(jìn)行加號(hào)(+)運(yùn)算驯击,最終得到是一個(gè)拼接的新的字符串烁兰。+ 號(hào)操作到底做了什么?

上面注釋說明了這個(gè)拼接的原理是由StringBuilder或者StringBuffer類和里面的append方法實(shí)現(xiàn)拼接徊都,然后調(diào)用 toString() 把拼接的對(duì)象轉(zhuǎn)換成字符串對(duì)象沪斟,最后把得到字符串對(duì)象的地址賦值給變量。

結(jié)合這個(gè)理解暇矫,我們下面畫一個(gè)內(nèi)存圖來分析主之。

file

大致內(nèi)存過程

1)常量池創(chuàng)建“ab”對(duì)象,并賦值給st1袱耽,所以st1指向了“ab”

2)常量池創(chuàng)建“abc”對(duì)象杀餐,并賦值給st2干发,所以st2指向了“abc”

3)由于這里走的+的拼接方法朱巨,所以第三步是使用StringBuffer類的append方法,得到了“abc”枉长,這個(gè)時(shí)候內(nèi)存0x0011表示的是一個(gè)StringBuffer對(duì)象冀续,注意不是String對(duì)象。

4)調(diào)用了Object的toString方法把StringBuffer對(duì)象裝換成了String對(duì)象必峰。

5)把String對(duì)象(0x0022)賦值給st3

所以洪唐,st3和st2進(jìn)行==判斷結(jié)果是不相等,因?yàn)閮蓚€(gè)對(duì)象內(nèi)存地址不同吼蚁。

總結(jié):

這篇的面試題凭需,完全就是要求掌握J(rèn)DK API中一些注解和原理,以及內(nèi)存圖分析肝匆,才能得到正確的結(jié)果粒蜈,我承認(rèn)是畫內(nèi)存圖讓我理解了答案為什么是這樣。

畫完內(nèi)存圖之后旗国,得到答案枯怖,你確實(shí)會(huì)發(fā)現(xiàn)很有趣,最后才會(huì)有原來如此的感嘆能曾。

作者:Anthony_tester

原文:
https://blog.csdn.net/u011541946/article/details/79865160

本文僅供學(xué)習(xí)之用度硝,版權(quán)歸原作者所有肿轨,如有侵權(quán)請(qǐng)聯(lián)系刪除。

我將面試題和答案都整理成了PDF文檔蕊程,還有一套學(xué)習(xí)資料椒袍,涵蓋Java虛擬機(jī)、spring框架存捺、Java線程槐沼、數(shù)據(jù)結(jié)構(gòu)、設(shè)計(jì)模式等等捌治,但不僅限于此岗钩。

關(guān)注公眾號(hào)【java圈子】獲取資料,還有優(yōu)質(zhì)文章每日送達(dá)肖油。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末兼吓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子森枪,更是在濱河造成了極大的恐慌视搏,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件县袱,死亡現(xiàn)場離奇詭異浑娜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)式散,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門筋遭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人暴拄,你說我怎么就攤上這事漓滔。” “怎么了乖篷?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵响驴,是天一觀的道長。 經(jīng)常有香客問我撕蔼,道長豁鲤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任鲸沮,我火速辦了婚禮琳骡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘诉探。我一直安慰自己日熬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著竖席,像睡著了一般耘纱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上毕荐,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天束析,我揣著相機(jī)與錄音,去河邊找鬼憎亚。 笑死员寇,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的第美。 我是一名探鬼主播蝶锋,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼什往!你這毒婦竟也來了扳缕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤别威,失蹤者是張志新(化名)和其女友劉穎躯舔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體省古,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡粥庄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了豺妓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惜互。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖科侈,靈堂內(nèi)的尸體忽然破棺而出载佳,到底是詐尸還是另有隱情炒事,我是刑警寧澤臀栈,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站挠乳,受9級(jí)特大地震影響权薯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜睡扬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一盟蚣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卖怜,春花似錦屎开、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蔼两。三九已至,卻和暖如春逞度,著一層夾襖步出監(jiān)牢的瞬間额划,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國打工档泽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留俊戳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓馆匿,卻偏偏與公主長得像抑胎,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子渐北,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355