當前位置: 妍妍網 > 碼農

面試官:String 能儲存多少個字元?

2024-04-19碼農

作者:念念清晰
連結:https://juejin.cn/post/7343883765540831283

  • 首先String的length方法返回是int。 所以理論上長度一定不會超過int的最大值。

  • 編譯器源碼如下,限制了字串長度大於等於65535就會編譯不透過

  • privatevoid checkStringConstant(DiagnosticPosition var1, Object var2) {if (this.nerrs == 0 && var2 != null && var2 instanceofString && ((String)var2).length() >= 65535) {this.log.error(var1, "limit.string", newObject[0]); ++this.nerrs; }}

    Java中的字元常量都是使用UTF8編碼的,UTF8編碼使用1~4個字節來表示具體的Unicode字元。所以有的字元占用一個字節,而我們平時所用的大部份中文都需要3個字節來儲存。

    //65534個字母,編譯透過String s1 = "dd..d";//21845個中文」自「,編譯透過String s2 = "自自...自";//一個英文字母d加上21845個中文」自「,編譯失敗String s3 = "d自自...自";

    對於s1,一個字母d的UTF8編碼占用一個字節,65534字母占用65534個字節,長度是65534,長度和儲存都沒超過限制,所以可以編譯透過。

    對於s2,一個中文占用3個字節,21845個正好占用65535個字節,而且字串長度是21845,長度和儲存也都沒超過限制,所以可以編譯透過。

    對於s3,一個英文字母d加上21845個中文」自「占用65536個字節,超過了儲存最大限制,編譯失敗。

    1.JVM規範對常量池有所限制。量池中的每一種數據項都有自己的型別。Java中的UTF-8編碼的Unicode字串在常量池中以CONSTANTUtf8型別表示。CONSTANTUtf8的數據結構如下:

    CONSTANT_Utf8_info {u1 tag;u2 length;u1 bytes[length];}

    我們重點關註下長度為 length 的那個bytes陣列,這個陣列就是真正儲存常量數據的地方,而 length 就是陣列可以儲存的最大字節數。length 的型別是u2,u2是無符號的16位元整數,因此理論上允許的的最大長度是2^16-1=65535。所以上面byte陣列的最大長度可以是65535

    2.執行時限制

    String 執行時的限制主要體現在 String 的建構函式上。下面是 String 的一個建構函式:

    publicString(charvalue[], int offset, int count) { ...}

    上面的count值就是字串的最大長度。在Java中,int的最大長度是2^31-1。所以在執行時,String 的最大長度是2^31-1。

    但是這個也是理論上的長度,實際的長度還要看你JVM的記憶體。我們來看下,最大的字串會占用多大的記憶體。

    (2^31-1)*16/8/1024/1024/1024 = 2GB

    所以在最壞的情況下,一個最大的字串要占用4GB的記憶體。如果你的虛擬機器不能分配這麽多記憶體的話,會直接報錯的。

    補充 JDK9以後對String的儲存進行了最佳化。底層不再使用char陣列儲存字串,而是使用byte陣列。對於LATIN1字元的字串可以節省一倍的記憶體空間。

    熱門推薦