Java 中 String 字符串可以有多長(zhǎng)?65535?
毫無(wú)疑問(wèn) String 是作為一個(gè) Java 開(kāi)發(fā)工程師天天都需要打交道的類,那么如果問(wèn)你 String 字符串的最大長(zhǎng)度是多少你知道嗎?
有的小伙伴可能想都沒(méi)想,就直接回答 65535,那么問(wèn)題來(lái)了,真的嗎?今天阿粉就帶你研究一下。
首先對(duì)于 String 我們可以有下面幾種用法:
- 定義一個(gè) String 類型的變量:private static final String STRING_TEST = "xxxxxxxxxxx"; 或者 String newString = "newString";
- 通過(guò)在方法中定義 String 類型的變量,通過(guò)字節(jié)流創(chuàng)建字符串:byte[] bytes = new byte[length];String s = new String(bytes);;
有朋友可能會(huì)說(shuō),這兩種不都是定義一個(gè)字符串變量,有什么區(qū)別嗎?表面上看是沒(méi)什么區(qū)別,但是實(shí)際上區(qū)別還是蠻大的。
首先第一種方式定一個(gè)靜態(tài)類變量,或者普通的字符串變量,這種形式字符串是存放在棧中的;而第二種方式字符串是存放在堆中的。這個(gè)時(shí)候有的小伙伴又要問(wèn)了,這存在不同的地方有什么關(guān)系呢?首先這關(guān)系可大了!
當(dāng)字符串存放在棧中的時(shí)候,根據(jù) class 文件的結(jié)果規(guī)范,我們可以看到所采用的的存儲(chǔ)格式是這樣的:
- CONSTANT_Utf8_info {
- u1 tag;
- u2 length;
- u1 bytes[length];
- }
其中 u2 是一種類似于Java 中int 一樣的數(shù)據(jù)類型,只是表示的是一個(gè) 2 個(gè)字節(jié)的數(shù)據(jù)類型,只不過(guò) int 是 4 個(gè)字節(jié),這也就意味著允許的最大長(zhǎng)度為 65535 個(gè)字符。所以我們可以得出一個(gè)結(jié)果,當(dāng)字符串存放在棧內(nèi)存中的時(shí)候,字符串的長(zhǎng)度可以達(dá)到 65535。
看到這里小伙伴又不耐煩了,說(shuō)到:你看吧,我就說(shuō)是 65535 吧,還不信。
別急,到這里我們才說(shuō)了一半,接下來(lái)我們?cè)诳纯吹诙N方式。很顯然第二種方式不管是通過(guò)字節(jié)流的方式,還是 new 一個(gè)對(duì)象,存放的位置都是早 Java 的堆內(nèi)存中,而且通過(guò) String 的源碼,我們可以看到了,底層是通過(guò)一個(gè) char[] 數(shù)組來(lái)存放的。
- private final char value[];
那么我們就知道了,字符傳的大小就跟數(shù)組的長(zhǎng)度有直接關(guān)系了,另外在定義數(shù)組長(zhǎng)度的時(shí)候,我們最多只能定義 int 類型的最大值,也就是Integer.MAX_VALUE = 0x7fffffff; 而且 String 類的 length() 方法的返回值也可以看出來(lái),返回的類型是 int ,數(shù)值最大也是Integer.MAX_VALUE = 0x7fffffff;
- /**
- * Returns the length of this string.
- * The length is equal to the number of <a href="Character.html#unicode">Unicode
- * code units</a> in the string.
- *
- * @return the length of the sequence of characters represented by this
- * object.
- */
- public int length() {
- return value.length;
- }
所以看到這里,我們又得出了一個(gè)結(jié)果,**當(dāng)字符串存放在堆內(nèi)存的時(shí)候,最大的長(zhǎng)度為 Integer.MAX_VALUE = 0x7fffffff; **。不過(guò)需要注意的是,這個(gè)數(shù)值是理論上的,其實(shí)很多虛擬機(jī)會(huì)在數(shù)組中加入一些字符,所以實(shí)際的數(shù)值是達(dá)不到這么多,另外我們?cè)?ArrayList 中也可以看到這個(gè)驗(yàn)證,這里定義的最大值就是Integer.MAX_VALUE - 8; 而不直接采用最大值。
此外上面說(shuō)的最大值是在我們的虛擬機(jī)有這么大的內(nèi)存的前提下,如果說(shuō)我們的虛擬機(jī)配置的內(nèi)存比這個(gè)要小,那也是達(dá)不到這么大。我們可以通過(guò) JVM 參數(shù)來(lái)配置虛擬機(jī)的內(nèi)存大小,-Xms512m 設(shè)置堆內(nèi)存初始值大小。-Xmx1024m 設(shè)置堆內(nèi)存最大值。下面是阿粉在自己的電腦上測(cè)試的效果,可以看到,當(dāng)開(kāi)始提示Requested array size exceeds VM limit,后面因?yàn)榘⒎鄣碾娔X內(nèi)存不夠了,所以一直分配失敗,達(dá)不到最大值,只能降低長(zhǎng)度了。
另外還要注意一個(gè)點(diǎn),那就是我們?cè)谶@里說(shuō)的長(zhǎng)度針對(duì)的都是英文字符,如果是是中文的話是沒(méi)有那么長(zhǎng)的,那么如果對(duì)應(yīng)中文的話字符串會(huì)有多長(zhǎng)呢?