欧美vvv,亚洲第一成人在线,亚洲成人欧美日韩在线观看,日本猛少妇猛色XXXXX猛叫

新聞資訊

    老套的筆試題

    在一些老套的筆試題中,會要你判斷s1==s2為false還是true,s1.(s2)為false還是true。

    String s1 = new String("xyz");
    String s2 = "xyz";
    System.out.println(s1 == s2);
    System.out.println(s1.equals(s2));

    對于這種題,你總能很快的給出標準答案:==比較的是對象地址,方法比較的是真正的字符數組。所以輸出的是false和true。

    上面的屬于最低階的題目,沒有什么難度。

    現在這種老套的題目已經慢慢消失了,取而代之的是有一些變形的新題目:

    String s1 = "aa";
    String s2 = "bb";
    String str1 = s1 + s2;
    String str2 = "aabb";
    //輸出什么呢???
    System.out.println(str1 == str2);
    final String s3 = "cc";
    final String s4 = "dd";
    String str3 = s3 + s4;
    String str4 = "ccdd";
    //又輸出什么呢???
    System.out.println(str3 == str4);

    難度提升了一些,但思考一下也不難得出答案是false和true。

    今天的文章就是以這幾個題目展開的。

    對象的創建

    先簡單看一下類的結構:

    可以發現,里面有一個value屬性,是真正存儲字符的char數組。

    在執行 s = "xyz";的時候,在堆區創建了一個對象,一個char數組對象。

    如何證明創建了一個對象和一個char數組對象呢?我們可以通過IDEA的Debug功能驗證:

    注意看我截圖的位置,在執行完 s = "xyz";之后,再次點擊load ,Diff欄的和char[]分別加了1,表示在內存中新增了一個char數組對象和一個對象。

    現在,我們再來看 s = new ("xyz");創建了幾個對象。

    從這張Debug動圖中,我們可以得出在 s = new ("xyz");之后,創建了兩個對象和一個char數組對象。

    又因為 s = new ("xyz");的s引用只能指向一個對象出現未結束字符串常量錯誤,重裝瀏覽器能解決嗎,可以畫出內存分布圖:

    從圖中可以看到,在堆區,有兩個對象,這兩個對象的value都指向同一個char數組對象。

    那么問題來了,下面的那個對象根本就沒被引用,也就是說他沒有被用到,那么它到底是干什么的呢?

    占了內存空間又不使用,難道這是JDK的設計缺陷?

    很顯然不是JDK的缺陷,JDK雖然確實有設計缺陷,但不至于這么明顯,這么愚蠢。

    那下面的那個對象是干什么的呢?

    答案是用于駐留到字符串常量池中去的,注意,這里我用了一個駐留,并不是直接把對象放到字符串常量池里面去,有什么區別我們后面再講。

    這里出現了字符串常量池的概念,我在 s = new ("xyz")創建了幾個實例你真的能答對嗎?中也有過比較詳細的介紹,有興趣的可以去看一下,這里不再重復了。

    你只需要知道,字符串常量池在JVM源碼中對應的類是,底層實現是一個。

    我們以 s = new ("xyz");為例:

    首先去找字符串常量池找,看能不能找到“xyz”字符串對應對象的引用,如果字符串常量池中找不到:

    如果字符串常量池中能找到:

    而 s = "xyz";是怎么樣的邏輯:

    首先去找字符串常量池找,看能不能找到“xyz”字符串的引用,如果字符串常量池中能找不到:

    如果字符串常量池中能找到:

    總結而言就是:

    對于 s = new ("xyz");這種形式創建字符串對象,如果字符串常量池中能找到,創建一個對象;如果如果字符串常量池中找不到,創建兩個對象。

    對于 s = "xyz";這種形式創建字符串對象,如果字符串常量池中能找到,不會創建對象;如果如果字符串常量池中找不到,創建一個對象。

    所以,在日常開發中,能用 s = "xyz";盡量不用 s = new ("xyz");,因為可以少創建一個對象,節省一部分空間。

    需要強調的是,字符串常量池存的不是字符串也不是對象,而是一個個,里面的value指向的才是對象,為了不讓表述變得復雜,我省略了的存在,但不代表它就不存在。

    上文提到的駐留就是新建指向對象,并把存入字符串常量池的過程。

    在網上一些文章中,一些作者可能是為了讓讀者更好的理解,省略了一些這些,一定要注意辨別區分。

    達成以上共識之后,我們再回顧一下那個老套的筆試題。

    String s1 = new String("xyz");
    String s2 = "xyz";
    //為什么輸出的是false呢?
    System.out.println(s1 == s2);
    //為什么輸出的是true呢?
    System.out.println(s1.equals(s2));

    有了上面的基礎之后,我們畫出對應的內存圖,s1 == s2為什么是false就一目了然了。

    因為方法比較的真正的char數據,而s1和s2最終指向的都是同一個char數組對象,所以s1.(s2)等于true。

    關于他們最終指向的都是同一個char數組對象這一觀點,也可以通過反射證明:

    我修改了str1指向的對象的value,str2指向的對象也被影響了。

    字符串拼接

    現在,我們再來看一下變式題:

    String s1 = "aa";
    String s2 = "bb";
    String str1 = s1 + s2;
    String str2 = "aabb";
    //為什么輸出的是false
    System.out.println(str1 == str2);

    對于這個題目,我們需要先看一下這段代碼的字節碼。

    字節碼指令看不懂沒有關系,看我用紅色框框起來的部分就行了,可以看到居然出現了。

    什么意思呢,就是說 str1 = s1 + s2;會被編譯器會優化成new ().("aa").("bb").();

    里面的方法就是對char數組進行操作,那的方法做了什么呢?

    從源碼中可以看到,里面的方法調用的是類里面的(char value[], int , int count)構造方法,這個方法做了什么呢?

    注意,并沒有駐留到字符串常量池里面去,這個很關鍵!!!畫一個圖理解一下:

    也就是說str2指向的對象并沒有駐留到字符串常量池出現未結束字符串常量錯誤,重裝瀏覽器能解決嗎,而str1指向的對象駐留到字符串常量池里面去了,且他們并不是同一個對象。所以str1 == str2還是false

    因為復制一份char數組對象,所以如果我們改變其中一個char數組的話,另一個也不會造成影響:

    把其中變成丑比之后,另一個還是帥比,也說明了兩個對象用的不是同一份char數組。

    方法

    上面說到,調用的方法創建的對象是不會駐留到字符串常量池的,那如果我偏要駐留到字符串常量池呢?有沒有辦法呢?

    有的,類的方法就可以幫你完成這個事情。

    以這段代碼為例:

    String s1 = "aa";
    String s2 = "bb";
    String str = s1 + s2;
    str.intern();

    在執行str.();之前,內存圖是這樣的:

    在執行str.();之后,內存圖是這樣的:

    方法就是創建了一個對象,并把value指向對象,然后把通過hash定位存到對應的字符串成常量池中。當然,前提是字符串常量池中原來沒有對應的。

    沒了,方法,就是這么簡單,一句話給你說清楚了。

    編譯優化

    寫到這里,好像只有一個坑沒有填。就是這個題為什么輸出的是true。

    final String s3 = "cc";
    final String s4 = "dd";
    String str3 = s3 + s4;
    String str4 = "ccdd";
    //為什么輸出的是true呢???
    System.out.println(str3 == str4);

    這道題和上面那道題相比,有點相似,在原來的基礎上加了兩個final關鍵字。我們先看一下這段代碼的字節碼:

    又是一段字節碼指令,不需要看懂,你點一下#4,居然就可以看到“ccdd”字符串。

    原來,用final修飾后,JDK的編譯器會識別優化,會把 str3 = s3 + s4;優化成 str3 = "ccdd"。

    所以原題就相當于:

    String str3 = "ccdd";
    String str4 = "ccdd";
    //為什么輸出的是true呢???
    System.out.println(str3 == str4);

    這樣的題目還難嗎?是不是那不管str3和str4怎么比,肯定是相等的。

    總結

    對于Java程序員來說就是“最熟悉的陌生人”,你說簡單,它確實簡單。你說它難,深究起來確實也有難度,但這些題目,只要你腦海里有一副內存圖就會很簡單。

    面試題也只會越來越難,這個行業看起來也越來越內卷,但只要我學的快,內卷就卷不到我。

    好了,今天就寫到了,我要去打游戲了。

    希望這篇文章,能對你有一點幫助。

    我對每一篇發出去的文章負責,文中涉及知識理論,我都會盡量在官方文檔和權威書籍找到并加以驗證。但即使這樣,我也不能保證文章中每個點都是正確的,如果你發現錯誤之處,歡迎指出,我會對其修正。

    所以,不要猶豫了,給點正反饋,答應我,一鍵三連(關注、點贊、再看)好嗎?

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有