Java 中的 String 有沒有長度限制

轉(zhuǎn)載:
https://juejin.im/post/5d53653f5188257315539f9a

String是Java中很重要的一個數(shù)據(jù)類型,除了基本數(shù)據(jù)類型以外,String是被使用的最廣泛的了,但是,關(guān)于String,其實還是有很多東西容易被忽略的。
就如本文我們要討論的問題:Java中的String有沒有長度限制?
這個問題要分兩個階段看,分別是編譯期和運行期。不同的時期限制不一樣。

編譯期

首先,我們先來合理的推斷一下,當(dāng)我們在代碼中使用String s = "";的形式來定義String對象的時候,""中字符的個數(shù)有沒有限制呢?
既然是合理的推斷,那就要要足夠的依據(jù),所以我們可以從String的源碼入手,根據(jù)public String(char value[], int offset, int count)的定義,count是int類型的,所以,char value[]中最多可以保存Integer.MAX_VALUE個,即2147483647字符。(jdk1.8.0_73)
但是,實驗證明,String s = "";中,最多可以有65534個字符。如果超過這個個數(shù)。就會在編譯期報錯。

public static void main(String[] args) {

    String s = "a...a";// 共65534個a
    System.out.println(s.length());

    String s1 = "a...a";// 共65535個a
    System.out.println(s1.length());
}

以上代碼,會在String s1 = "a...a";// 共65535個a處編譯失敗:

? javac StringLenghDemo.java
StringLenghDemo.java:11: 錯誤: 常量字符串過長

明明說好的長度限制是2147483647,為什么65535個字符就無法編譯了呢?

當(dāng)我們使用字符串字面量直接定義String的時候,是會把字符串在常量池中存儲一份的。那么上面提到的65534其實是常量池的限制。
常量池中的每一種數(shù)據(jù)項也有自己的類型。Java中的UTF-8編碼的Unicode字符串在常量池中以CONSTANT_Utf8類型表示。
CONSTANTUtf8info是一個CONSTANTUtf8類型的常量池數(shù)據(jù)項,它存儲的是一個常量字符串。常量池中的所有字面量幾乎都是通過CONSTANTUtf8info描述的。CONSTANTUtf8_info的定義如下:

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

由于本文的重點并不是CONSTANTUtf8info的介紹,這里就不詳細(xì)展開了,我們只需要我們使用字面量定義的字符串在class文件中,是使用CONSTANTUtf8info存儲的,而CONSTANTUtf8info中有u2 length;表明了該類型存儲數(shù)據(jù)的長度。
u2是無符號的16位整數(shù),因此理論上允許的的最大長度是2^16=65536。而 java class 文件是使用一種變體UTF-8格式來存放字符的,null 值使用兩個 字節(jié)來表示,因此只剩下 65536- 2 = 65534個字節(jié)。
關(guān)于這一點,在the class file format spec中也有明確說明:

The length of field and method names, field and method descriptors, and other constant string values is limited to 65535 characters by the 16-bit unsigned length item of the CONSTANTUtf8info structure (§4.4.7). Note that the limit is on the number of bytes in the encoding and not on the number of encoded characters. UTF-8 encodes some characters using two or three bytes. Thus, strings incorporating multibyte characters are further constrained.

也就是說,在Java中,所有需要保存在常量池中的數(shù)據(jù),長度最大不能超過65535,這當(dāng)然也包括字符串的定義咯。

運行期

上面提到的這種String長度的限制是編譯期的限制,也就是使用String s= "";這種字面值方式定義的時候才會有的限制。
那么。String在運行期有沒有限制呢,答案是有的,就是我們前文提到的那個Integer.MAX_VALUE ,這個值約等于4G,在運行期,如果String的長度超過這個范圍,就可能會拋出異常。(在jdk 1.9之前)
int 是一個 32 位變量類型,取正數(shù)部分來算的話,他們最長可以有

2^31-1 =2147483647 個 16-bit Unicodecharacter

2147483647 * 16 = 34359738352 位
34359738352 / 8 = 4294967294 (Byte)
4294967294 / 1024 = 4194303.998046875 (KB)
4194303.998046875 / 1024 = 4095.9999980926513671875 (MB)
4095.9999980926513671875 / 1024 = 3.99999999813735485076904296875 (GB)

有近 4G 的容量。

作者:HollisChuang
鏈接:https://juejin.im/post/5d53653f5188257315539f9a
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 14,257評論 0 38
  • 注:都是在百度搜索整理的答案,如有侵權(quán)和錯誤,希告知更改。 一、哪些情況下的對象會被垃圾回收機制處理掉 ?當(dāng)對象對...
    Jenchar閱讀 3,311評論 3 2
  • 前言 RTFSC (Read the fucking source code )才是生活中最重要的。我們天天就是要...
    二毛_coder閱讀 525評論 1 1
  • 夫君子之行,靜以修身,儉以養(yǎng)德。 非淡泊無以明志,非寧靜無以致遠(yuǎn)。 夫?qū)W須靜也,才須學(xué)也。 非學(xué)無以廣才,非志無以...
    張應(yīng)榮閱讀 920評論 0 1
  • 夏家在解放前是經(jīng)商的大戶。小殘軒店址是夏家祖屋,是八十年代落實政策后歸還至夏小嵐父親手上的。 夏小嵐兒時因耳殘輟學(xué)...
    老都閱讀 509評論 7 17

友情鏈接更多精彩內(nèi)容