這個(gè)問(wèn)題要分兩個(gè)階段看,分別是編譯期和運(yùn)行期。不同的時(shí)期限制不一樣。
01 編譯期
首先,我們先來(lái)合理的推斷一下,當(dāng)我們?cè)诖a中使用String s = "";的形式來(lái)定義String對(duì)象的時(shí)候,""中字符的個(gè)數(shù)有沒(méi)有限制呢?
既然是合理的推斷,那就要要足夠的依據(jù),所以我們可以從String的源碼入手,根據(jù)public String(char value[], int offset, int count)的定義,count是int類(lèi)型的,所以,char value[]中最多可以保存Integer.MAX_VALUE個(gè),即2147483647字符。(jdk1.8.0_73)
但是,實(shí)驗(yàn)證明,String s = "";中,最多可以有65534個(gè)字符。如果超過(guò)這個(gè)個(gè)數(shù)。就會(huì)在編譯期報(bào)錯(cuò)。
public static void main(String[] args) { String s = "a...a";// 共65534個(gè)a System.out.println(s.length()); String s1 = "a...a";// 共65535個(gè)a System.out.println(s1.length()); }
以上代碼,會(huì)在String s1 = "a...a";// 共65535個(gè)a處編譯失敗:
? javac StringLenghDemo.java StringLenghDemo.java:11: 錯(cuò)誤: 常量字符串過(guò)長(zhǎng)
明明說(shuō)好的長(zhǎng)度限制是2147483647,為什么65535個(gè)字符就無(wú)法編譯了呢?
當(dāng)我們使用字符串字面量直接定義String的時(shí)候,是會(huì)把字符串在常量池中存儲(chǔ)一份的。那么上面提到的65534其實(shí)是常量池的限制。
常量池中的每一種數(shù)據(jù)項(xiàng)也有自己的類(lèi)型。Java中的UTF-8編碼的Unicode字符串在常量池中以CONSTANT_Utf8類(lèi)型表示。
CONSTANTUtf8info是一個(gè)CONSTANTUtf8類(lèi)型的常量池?cái)?shù)據(jù)項(xiàng),它存儲(chǔ)的是一個(gè)常量字符串。常量池中的所有字面量幾乎都是通過(guò)CONSTANTUtf8info描述的。CONSTANTUtf8_info的定義如下:
CONSTANT_Utf8_info { u1 tag; u2 length; u1 bytes[length]; }
由于本文的重點(diǎn)并不是CONSTANTUtf8info的介紹,這里就不詳細(xì)展開(kāi)了,我們只需要我們使用字面量定義的字符串在class文件中,是使用CONSTANTUtf8info存儲(chǔ)的,而CONSTANTUtf8info中有u2 length;表明了該類(lèi)型存儲(chǔ)數(shù)據(jù)的長(zhǎng)度。
u2是無(wú)符號(hào)的16位整數(shù),因此理論上允許的的最大長(zhǎng)度是2^16=65536。而 java class 文件是使用一種變體UTF-8格式來(lái)存放字符的,null 值使用兩個(gè) 字節(jié)來(lái)表示,因此只剩下 65536- 2 = 65534個(gè)字節(jié)。
關(guān)于這一點(diǎn),在the class file format spec中也有明確說(shuō)明:
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.
也就是說(shuō),在Java中,所有需要保存在常量池中的數(shù)據(jù),長(zhǎng)度最大不能超過(guò)65535,這當(dāng)然也包括字符串的定義咯。
02 運(yùn)行期
上面提到的這種String長(zhǎng)度的限制是編譯期的限制,也就是使用String s= "";這種字面值方式定義的時(shí)候才會(huì)有的限制。
那么。String在運(yùn)行期有沒(méi)有限制呢,答案是有的,就是我們前文提到的那個(gè)Integer.MAX_VALUE ,這個(gè)值約等于4G,在運(yùn)行期,如果String的長(zhǎng)度超過(guò)這個(gè)范圍,就可能會(huì)拋出異常。(在jdk 1.9之前)
int 是一個(gè) 32 位變量類(lèi)型,取正數(shù)部分來(lái)算的話,他們最長(zhǎng)可以有
2^31-1 =2147483647 個(gè) 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)
-
JAVA
+關(guān)注
關(guān)注
19文章
2970瀏覽量
104834 -
字符串
+關(guān)注
關(guān)注
1文章
579瀏覽量
20549
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論