java中的String定義的字面量最大長(zhǎng)度是多少
java的String對(duì)象底層是有字符數(shù)組存儲(chǔ)的,理論上char[] 最大長(zhǎng)度是int的最大值,實(shí)際
思路:
首先,String字面常量是由String類來維護(hù)的,并且在編譯時(shí)就可以確定(具體請(qǐng)參考String常量池)。因而,如果String字面常量存在一個(gè)最大的長(zhǎng)度(目前暫且假設(shè)),而我們使用的字面常量又超過了這個(gè)極限,那么,在編譯期間,編譯器就能夠給出錯(cuò)誤信息。因此,我們可以使用IO流生成Java文件,文件的內(nèi)容就是聲明一個(gè)String對(duì)象,然后使用字面常量賦值,根據(jù)動(dòng)態(tài)編譯結(jié)果,調(diào)整字面常量的長(zhǎng)度,最后得出字面常量的最大長(zhǎng)度值
根據(jù)以下代碼得出結(jié)論(代碼來自書《Java深入解析:透析Java本質(zhì)的36個(gè)話題 》):
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
public class LiteralLength {
public static void main(String[] args) throws Exception {
String fileName = "D:/Literal.java";
StringBuilder prefix = new StringBuilder();
prefix.append("public class Literal{ String s = \"");
int low = 0;
int high = 100_0000;
int mid = (low + high)/2;
StringBuilder literal = new StringBuilder(high);
int result;
String ch = "A";
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//自定義錯(cuò)誤輸出流 取代System的err
OutputStream err = new OutputStream() {
@Override
public void write(int b) throws IOException {
}
};
int max = 0;
for (int i = 0; i < mid; i++) {
literal.append(ch);
}
while(low <= high){
StringBuilder fileContent
= new StringBuilder(literal.length() + prefix.length() * 2);
fileContent.append(prefix);
fileContent.append(literal);
fileContent.append("\";}");
FileWriter w = new FileWriter(fileName);
BufferedWriter bw = new BufferedWriter(w);
bw.write(fileContent.toString());
bw.close();
w.close();//生成java文件
result = compiler.run(null, null, err, fileName);
//代碼點(diǎn)的數(shù)量
int codePointCount = literal.codePointCount(0, literal.length());
if(result == 0){//0表示沒有編譯錯(cuò)誤
low = mid + 1;
mid = (low + high)/2;
max = codePointCount;
for (int i = codePointCount; i < mid; i++) {
literal.append(ch);
}
System.out.println("長(zhǎng)度" + max
+ "編譯成功,增加長(zhǎng)度至" + mid);
}else{
//編譯錯(cuò)誤,說明字面量太長(zhǎng)
high = mid - 1;
mid = (low + high)/2;
System.err.println("長(zhǎng)度" + codePointCount
+ "編譯失敗,減少長(zhǎng)度至" + mid);
int start = ch.length() == 1? mid : mid *2;
literal.delete(start, literal.length());
}
}
err.close();
System.out.println("最大字面量長(zhǎng)度:" + max);
}
}
輸出結(jié)果:
長(zhǎng)度500000編譯失敗,減少長(zhǎng)度至249999
長(zhǎng)度249999編譯失敗,減少長(zhǎng)度至124999
長(zhǎng)度124999編譯失敗,減少長(zhǎng)度至62499
長(zhǎng)度62499編譯成功,增加長(zhǎng)度至93749
長(zhǎng)度93749編譯失敗,減少長(zhǎng)度至78124
長(zhǎng)度78124編譯失敗,減少長(zhǎng)度至70311
長(zhǎng)度70311編譯失敗,減少長(zhǎng)度至66405
長(zhǎng)度66405編譯失敗,減少長(zhǎng)度至64452
長(zhǎng)度64452編譯成功,增加長(zhǎng)度至65428
長(zhǎng)度65428編譯成功,增加長(zhǎng)度至65916
長(zhǎng)度65916編譯失敗,減少長(zhǎng)度至65672
長(zhǎng)度65672編譯失敗,減少長(zhǎng)度至65550
長(zhǎng)度65550編譯失敗,減少長(zhǎng)度至65489
長(zhǎng)度65489編譯成功,增加長(zhǎng)度至65519
長(zhǎng)度65519編譯成功,增加長(zhǎng)度至65534
長(zhǎng)度65534編譯成功,增加長(zhǎng)度至65542
長(zhǎng)度65542編譯失敗,減少長(zhǎng)度至65538
長(zhǎng)度65538編譯失敗,減少長(zhǎng)度至65536
長(zhǎng)度65536編譯失敗,減少長(zhǎng)度至65535
長(zhǎng)度65535編譯失敗,減少長(zhǎng)度至65534
最大字面量長(zhǎng)度:65534
但是若 修改代碼
String ch = "α";
結(jié)論 : 最大字面量長(zhǎng)度:32767
若 String ch = "字";
最大字面量長(zhǎng)度:21845
在class文件中,使用CONSTANT_Utf8_info表來存放各種常量字符串,包括String字面常量,類或接口的全限定名,方法及變量的名稱、描述符等。CONSTANT_Utf8_info表的結(jié)構(gòu)如表 所示。
從表3-1可知,CONSTANT_Utf8_info表使用2字節(jié)來表示字符串的長(zhǎng)度,因此,bytes數(shù)組的最大長(zhǎng)度為216−1,即65535字節(jié)??墒?,為什么4個(gè)字符(“A”、“á”、“字”與“㊣”)的運(yùn)行結(jié)果各不相同呢?原因在于,在CONSTANT_Utf8_info表中,從“\u0001”~“\u007f”,bytes使用1字節(jié)來表示,空字符(null,即“\u0000”)和從“\u0080”~“\u07ff”,使用2字節(jié)來表示,從“\u0800”~“\uffff”,使用3字節(jié)來表示,而對(duì)于增補(bǔ)字符,即代碼點(diǎn)范圍在“U+10000”~“U+10FFFF”之間的字符,使用6字節(jié)來表示。也可以這樣認(rèn)為,增補(bǔ)字符是使用一個(gè)代理對(duì)來表示的,而代理對(duì)的取值范圍為“\ud800”~“\udfff”,這些字符都在“\u0800”~“\uffff”之間,每個(gè)代理字符使用3字節(jié)表示,共6字節(jié)。上述的存儲(chǔ)是在class文件中的實(shí)現(xiàn),不要與Java程序中的字符相混淆,對(duì)于Java程序來說,“A”、“á”、“字”都使用一個(gè)char類型變量表示,即2字節(jié),而“[插圖]”(增補(bǔ)字符)使用兩個(gè)char類型變量表示,即4字節(jié)。
String字面常量的最大長(zhǎng)度與String在內(nèi)存中的最大長(zhǎng)度是不一樣的,后者的最大長(zhǎng)度為int類型的最大值,即2147483647,而前者根據(jù)字符(字符Unicode值)的不同,最大長(zhǎng)度也不同,最大長(zhǎng)度為65534(可手動(dòng)修改class文件,令輸出結(jié)果為65535)。
String字面常量的最大長(zhǎng)度是由CONSTANT_Utf8_info表來決定的,該長(zhǎng)度在編譯時(shí)確定,如果超過了CONSTANT_Utf8_info表bytes數(shù)組所能表示的上限,就會(huì)產(chǎn)生編譯錯(cuò)誤。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
上一篇:簡(jiǎn)單了解spring bean作用域?qū)傩詓ingleton和prototype的區(qū)別
欄 目:Java
下一篇:Java9 Stream Collectors新增功能(小結(jié))
本文標(biāo)題:java中的String定義的字面量最大長(zhǎng)度是多少
本文地址:http://www.jygsgssxh.com/a1/Java/8877.html
您可能感興趣的文章
- 01-10Java實(shí)現(xiàn)動(dòng)態(tài)模擬時(shí)鐘
- 01-10利用Java實(shí)現(xiàn)復(fù)制Excel工作表功能
- 01-10JavaWeb實(shí)現(xiàn)郵件發(fā)送功能
- 01-10java基于poi導(dǎo)出excel透視表代碼實(shí)例
- 01-10Java實(shí)現(xiàn)動(dòng)態(tài)數(shù)字時(shí)鐘
- 01-10基于Java驗(yàn)證jwt token代碼實(shí)例
- 01-10java實(shí)現(xiàn)液晶數(shù)字字體顯示當(dāng)前時(shí)間
- 01-10淺談Java中真的只有值傳遞么
- 01-10Java動(dòng)態(tài)顯示當(dāng)前日期和時(shí)間
- 01-10如何解決線程太多導(dǎo)致java socket連接池出現(xiàn)的問題


閱讀排行
- 1C語言 while語句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語言實(shí)現(xiàn)“百馬百擔(dān)”問題方法
- 4C語言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10Java實(shí)現(xiàn)動(dòng)態(tài)模擬時(shí)鐘
- 01-10Springboot中@Value的使用詳解
- 01-10JavaWeb實(shí)現(xiàn)郵件發(fā)送功能
- 01-10利用Java實(shí)現(xiàn)復(fù)制Excel工作表功能
- 01-10Java實(shí)現(xiàn)動(dòng)態(tài)數(shù)字時(shí)鐘
- 01-10java基于poi導(dǎo)出excel透視表代碼實(shí)例
- 01-10java實(shí)現(xiàn)液晶數(shù)字字體顯示當(dāng)前時(shí)間
- 01-10基于Java驗(yàn)證jwt token代碼實(shí)例
- 01-10Java動(dòng)態(tài)顯示當(dāng)前日期和時(shí)間
- 01-10淺談Java中真的只有值傳遞么
隨機(jī)閱讀
- 01-10delphi制作wav文件的方法
- 04-02jquery與jsp,用jquery
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10C#中split用法實(shí)例總結(jié)
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載


