我說我精通字符串,面試官居然問我Java中的String有沒有長度限制!?

String是Java中很重要的一個數據類型,除了基本數據類型之外,String是被使用的最普遍的了,可是,關於String,其實仍是有不少東西容易被忽略的。java

就如本文咱們要討論的問題:Java中的String有沒有長度限制?編碼

這個問題要分兩個階段看,分別是編譯期和運行期。不一樣的時期限制不同。spa

編譯期

首先,咱們先來合理的推斷一下,當咱們在代碼中使用String s = "";的形式來定義String對象的時候,""中字符的個數有沒有限制呢?code

既然是合理的推斷,那就要要足夠的依據,因此咱們能夠從String的源碼入手,根據public String(char value[], int offset, int count)的定義,count是int類型的,因此,char value[]中最多能夠保存Integer.MAX_VALUE個,即2147483647字符。(jdk1.8.0_73)orm

可是,實驗證實,String s = "";中,最多能夠有65534個字符。若是超過這個個數。就會在編譯期報錯。cdn

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個字符就沒法編譯了呢?three

當咱們使用字符串字面量直接定義String的時候,是會把字符串在常量池中存儲一份的。那麼上面提到的65534實際上是常量池的限制。ip

常量池中的每一種數據項也有本身的類型。Java中的UTF-8編碼的Unicode字符串在常量池中以CONSTANT_Utf8類型表示。字符串

CONSTANTUtf8info是一個CONSTANTUtf8類型的常量池數據項,它存儲的是一個常量字符串。常量池中的全部字面量幾乎都是經過CONSTANTUtf8info描述的。CONSTANTUtf8_info的定義以下:

CONSTANT_Utf8_info {
    u1 tag;
    u2 length;
    u1 bytes[length];
}
複製代碼

因爲本文的重點並非CONSTANTUtf8info的介紹,這裏就不詳細展開了,咱們只須要咱們使用字面量定義的字符串在class文件中,是使用CONSTANTUtf8info存儲的,而CONSTANTUtf8info中有u2 length;代表了該類型存儲數據的長度。

u2是無符號的16位整數,所以理論上容許的的最大長度是2^16=65536。而 java class 文件是使用一種變體UTF-8格式來存放字符的,null 值使用兩個 字節來表示,所以只剩下 65536- 2 = 65534個字節。

關於這一點,在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中,全部須要保存在常量池中的數據,長度最大不能超過65535,這固然也包括字符串的定義咯。

運行期

上面提到的這種String長度的限制是編譯期的限制,也就是使用String s= "";這種字面值方式定義的時候纔會有的限制。

那麼。String在運行期有沒有限制呢,答案是有的,就是咱們前文提到的那個Integer.MAX_VALUE ,這個值約等於4G,在運行期,若是String的長度超過這個範圍,就可能會拋出異常。(在jdk 1.9以前)

int 是一個 32 位變量類型,取正數部分來算的話,他們最長能夠有

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 的容量。

相關文章
相關標籤/搜索