我說我精通字串,面試官竟然問我Java中的String有沒有長度限制!?
String是Java中很重要的一個資料型別,除了基本資料型別以外,String是被使用的最廣泛的了,但是,關於String,其實還是有很多東西容易被忽略的。
就如本文我們要討論的問題:Java中的String有沒有長度限制?
這個問題要分兩個階段看,分別是編譯期和執行期。不同的時期限制不一樣。
編譯期
首先,我們先來合理的推斷一下,當我們在程式碼中使用String s = “”;的形式來定義String物件的時候,””中字元的個數有沒有限制呢?
既然是合理的推斷,那就要要足夠的依據,所以我們可以從String的原始碼入手,根據public String(char value[], int offset, int count)的定義,count是int型別的,所以,char value[]中最多可以儲存Integer.MAX_VALUE個,即2147483647字元。(jdk1.8.0_73)
但是,實驗證明,String s = “”;中,最多可以有65534個字元。如果超過這個個數。就會在編譯期報錯。
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個字元就無法編譯了呢?
當我們使用字串字面量直接定義String的時候,是會把字串在常量池中儲存一份的。那麼上面提到的65534其實是常量池的限制。
常量池中的每一種資料項也有自己的型別。Java中的UTF-8編碼的Unicode字串在常量池中以CONSTANT_Utf8型別表示。
CONSTANTUtf8info是一個CONSTANTUtf8型別的常量池資料項,它儲存的是一個常量字串。常量池中的所有字面量幾乎都是通過CONSTANTUtf8info描述的。CONSTANTUtf8_info的定義如下:
CONSTANT_Utf8_info
{
//vx耗:mbz_java_panlong 十年開發經驗程式設計師,免費解答,備註“MI”即可
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
//vx耗:mbz_java_panlong 十年開發經驗程式設計師,免費解答,備註“MI”即可
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 的容量。
(全文完)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70010294/viewspace-2847959/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 我說我精通字串,面試官竟然問我Java中的String有沒有長度限制!?|附視訊講解字串面試Java
- 面試官問我,使用Dubbo有沒有遇到一些坑?我笑了。面試
- 面試的反殺-你有沒有想要問我的面試
- 面試官問我:建立執行緒有幾種方式?我笑了面試執行緒
- 面試官問我MySQL索引,我面試MySql索引
- 面試官:你還有什麼想問我的?面試
- 面試官問我HTTP,我真的是面試HTTP
- 面試官:說一說CyclicBarrier的妙用!我:這個沒用過面試
- 面試官問我按鈕級別許可權怎麼控制,我說v-if,面試官說再見面試
- 面試官問我Redis叢集,我真的是面試Redis
- 面試官問我MySQL調優,我真的是面試MySql
- 【Nginx】面試官竟然問我Nginx如何生成縮圖,還好我看了這篇文章!!Nginx面試
- 面試別再問我String了面試
- 當面試官問我JDK Semaphore的原理時,我笑了面試JDK
- 面試官問我:spring、springboot、springcloud的區別,我笑了面試Spring BootGCCloud
- 面試官突然問我MySQL儲存過程,我竟然連基礎都不會!(詳細)面試MySql儲存過程
- 面試官問我JVM調優,我忍不住了!面試JVM
- 【Java8新特性】面試官問我:Java8中建立Stream流有哪幾種方式?Java面試
- 面試官問我會不會Elasticsearch,我語塞了...面試Elasticsearch
- 面試官:spring中定義bean的方法有哪些? 我一口氣說出了12種,把面試官征服了。面試SpringBean
- 當面試官問我Mybatis初始化原理時,我笑了面試MyBatis
- 面試官問我JVM記憶體結構,我真的是面試JVM記憶體
- 面試官,你再問我 Bit Operation 試試?面試
- 【MySQL】面試官問我:MySQL如何實現無資料插入,有資料更新?我是這樣回答的!MySql面試
- 面試官: 我必問的容器知識點!面試
- 說的好像有一點點道理,我都沒有反對
- 面試官:五年經驗,我不問問反射說不過去吧?面試反射
- “我沒有說謊,我何必說謊”,AI可以判斷歌曲表達的情緒AI
- 面試官:為什麼 Java 不把基本型別放在堆中?我竟然答不上來。。面試Java型別
- 面試官問我redis資料型別,我回答了8種面試Redis資料型別
- 面試官問我:什麼是JavaScript閉包,我該如何回答面試JavaScript
- 面試官,我會寫二分查詢法了!對,沒有 bug 的那種!面試
- 如果我是推薦演算法面試官,我會問哪些問題?演算法面試
- 面試官問我:如何在 Python 中解析和修改 XML面試PythonXML
- 面試官,不要再問我“Java GC垃圾回收機制”了面試JavaGC
- 【String註解驅動開發】面試官讓我說說:如何使用FactoryBean向Spring容器中註冊bean?面試BeanSpring
- 同事都說有SQL隱碼攻擊風險,我非說沒有SQL
- 面試官竟然問我怎麼實現分散式鎖?幸虧我總結了全套八股文面試分散式