<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      關于 Java String,這是面試的基礎,但是還有很多童鞋不能說清楚,所以本文將簡單而又透徹的說明一下那個讓你迷惑的 String



      在 Java 中,我們有兩種方式創(chuàng)建一個字符串
      String x = "abc"; String y = new String("abc");
      你常見也常寫第一種,很少見第二種,但面試還總問這類問題,雙引號和構造器兩種形式創(chuàng)建字符串到底有什么差別呢?

      先來看例子

      例子 1
      String a = "abcd"; String b = "abcd"; System.out.println(a == b); // True
      System.out.println(a.equals(b)); // True
      a == b 結(jié)果為 true,是因為 a 和 b 都指向 方法區(qū)(method area) 同一個字符串文字,內(nèi)存引用是同一個

      當多次創(chuàng)建相同的字符串文字時,只存儲每個不同字符串值的一個副本。這個叫做字符串留駐/留用,Java 中所有編譯期字符串常量都會被自動留駐

      例子 2
      String c = new String("abcd"); String d = new String("abcd");
      System.out.println(c == d); // False System.out.println(c.equals(d)); // True
      c==d 結(jié)果為 false,因為 c 和 d 的引用指向堆中不同的對象,不同的對象肯定有不同的內(nèi)存引用

      舉了兩個例子,文字描述有點懵?我們來試圖通過圖形來理解上述兩種情況:



      也許你已經(jīng)看看出來了,一個是在方法區(qū),一個是在堆中,在 JVM 模型中這是兩個不同的區(qū)域,也許你面試時也經(jīng)常被問到吧,來看下圖:



      再次提醒一下,所有 new 的對象都會在 Heap 中,這樣以后你就好區(qū)分了

      運行期字符串留駐

      上面說的字符串留駐是在編譯期,那么運行期可以嗎?答案是肯定的,我們需要一個函數(shù)來幫忙
      String c = new String("abcd").intern(); String d = new
      String("abcd").intern(); System.out.println(c == d); // Now true
      System.out.println(c.equals(d)); // True
      看到 c == d 結(jié)果為 true,你應該理解 intern (英文有拘留,軟禁的意思)的作用了,通過調(diào)用
      intern()方法,就好比把創(chuàng)建的字符串拘留在方法區(qū)一樣了

      在面試時甚至還會問你下面代碼創(chuàng)建了幾個對象:
      String d = new String("abcd")
      * 如果方法區(qū)已存在"abcd", 那么只創(chuàng)建一個 new String 的對象
      * 如果方法區(qū)沒有"abcd", 那么要創(chuàng)建兩個對象,一個在方法區(qū),一個在堆中
      所以,正常情況下我們沒必要使用構造器創(chuàng)建對象,因為這很可能會產(chǎn)生一個額外的沒用的對象,但是有例外哦,我們下面說
      String s = "abcd"; s = s.concat("ef");


      當我們想在字符串 s 后面拼接字符"ef"時,會在堆中創(chuàng)建一個新的對象,并將 s 的引用指向新創(chuàng)建的對象,由于 String 創(chuàng)建的是不可變對象,所以
      String 類中的所有方法都不會改變它自身,而是返回一個新的字符串(快打開你的 IDE,看看是否每個操作String 的方法最后都是返回有 return
      new String 字樣),到這里你也應該理解了一個道理:

      如果我們需要一個字符串被修改,我們最好使用 StringBuffer 或者
      StringBuilder,否則,由于每次操作字符串都會創(chuàng)建一個新的對象,而舊的對象不會有引用指向它,這樣我們會浪費很多垃圾回收的時間

      到這里還沒完,你有沒有想過為什么 String 會被設置/制造成 final?

      為什么 String 類被 final 修飾

      談及這個問題我們需要一些倒推的或者相互約束思維來思考

      字符串池的需求

      字符串池(String intern
      pool)是方法區(qū)域中的一個特殊存儲區(qū)域。當創(chuàng)建一個字符串時,如果該字符串已經(jīng)存在于池中,那么返回現(xiàn)有字符串的引用,而不是創(chuàng)建一個新對象。所以說,如果一個字符串是可變的,那么改變一個引用的值,將導致原本指向該值的引用獲取到錯誤的值

      緩存 hashcode


      字符串的hashcode在Java中經(jīng)常使用。例如,在HashMap或HashSet中。不可變保證hashcode始終是相同的,這樣就可以在不擔心更改的情況下兌現(xiàn)它。這意味著,不需要每次使用hashcode時都計算它。這樣更有效率。所以你會在
      String 類中看到下面的成員變量的定義:
      /** Cache the hash code for the string */ private int hash; // Default to 0
      安全性


      String被廣泛用作許多java類的參數(shù),例如網(wǎng)絡連接、打開文件等。如果字符串不是不可變的,連接或文件將被更改,這可能導致嚴重的安全威脅。該方法認為它連接到一臺機器上,但實際上并沒有。
      可變字符串也可能導致反射中的安全問題,因為參數(shù)是字符串。

      不可變對象天生是線程安全的

      由于不可變對象不能被更改,所以它們可以在多個線程之間自由共享。這消除了同步的需求。

      總之,出于效率和安全性的考慮,String 被設計為不可變的。這也是為什么在一般情況下,不可變類是首選的原因。

      附加說明

      關于不可變對象和不可變引用總是有同學搞不清楚
      final User user = new User();
      上面的代碼指的是 user 引用不能被更改指向內(nèi)存的其他地址,但是由于 User 是可變對象,我們可以調(diào)用 user 的 setter 方法修改其屬性

      在String類中包含很多學問,包括你對JVM模型的理解,這也就是為什么面試官為什么喜歡問String,主要考察你的基本功

      靈魂追問

      * String 和基本類型的包裝類如 Integer 和 Long 都被 final 修飾,但為什么不建議作為 synchronized
      同步塊的參數(shù)適用呢?
      * 基本類型自動裝箱你知道發(fā)生了什么嗎?和上一個問題有關系
      提高效率工具



      Material Theme UI

      這是一款 IDEA 的主題插件,安裝后,選擇 Material Palenight 主題,同時作出如下設置


      設置完后,你的 IDEA 就是下面這樣,引起極度舒適


      推薦閱讀

      * 每天用SpringBoot,還不懂RESTful API返回統(tǒng)一數(shù)據(jù)格式是怎么實現(xiàn)的?
      <https://mp.weixin.qq.com/s/q5cyK14WGiMm-R6NIFBcTg>
      * 雙親委派模型:大廠高頻面試題,輕松搞定 <https://mp.weixin.qq.com/s/Dnr1jLebvBUHnziZzSfcrA>
      * 面試還不知道BeanFactory和ApplicationContext的區(qū)別?
      <https://mp.weixin.qq.com/s/YBQB086ADBjHUmwrFQrWew>
      * 如何設計好的RESTful API <https://mp.weixin.qq.com/s/hR1TqkVzwZ_T8fuMnsM4hQ>
      * 紅黑樹,超強動靜圖詳解,簡單易懂 <https://mp.weixin.qq.com/s/ilND8u_8HGSTSrJiMB4X8g>
      歡迎持續(xù)關注公眾號:「日拱一兵」

      * 前沿 Java 技術干貨分享
      * 高效工具匯總 | 回復「工具」
      * 面試問題分析與解答
      * 技術資料領取 | 回復「資料」
      以讀偵探小說思維輕松趣味學習 Java 技術棧相關知識,本著將復雜問題簡單化,抽象問題具體化和圖形化原則逐步分解技術問題,技術持續(xù)更新,請持續(xù)關注......


      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點信息
      問題反饋
      郵箱:[email protected]
      QQ群:637538335
      關注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          欧美色图在线视频 | 人人摸人人舔 | 一级大片网址 | 91嫩|婷婷丨入口图片 | 在线播放少妇奶水过盛 | 一区二区三区不卡在线 | 国产特黄无码A片免费看 | 日韩有码第一页 | 日本少妇无码 | 性生活视频看看 |