java中的String定义的字面量最大长度是多少
作者:蓝色土耳其18 发布时间:2023-09-01 08:35:31
java的String对象底层是有字符数组存储的,理论上char[] 最大长度是int的最大值,实际
思路:
首先,String字面常量是由String类来维护的,并且在编译时就可以确定(具体请参考String常量池)。因而,如果String字面常量存在一个最大的长度(目前暂且假设),而我们使用的字面常量又超过了这个极限,那么,在编译期间,编译器就能够给出错误信息。因此,我们可以使用IO流生成Java文件,文件的内容就是声明一个String对象,然后使用字面常量赋值,根据动态编译结果,调整字面常量的长度,最后得出字面常量的最大长度值
根据以下代码得出结论(代码来自书《Java深入解析:透析Java本质的36个话题 》):
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();
//自定义错误输出流 取代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);
//代码点的数量
int codePointCount = literal.codePointCount(0, literal.length());
if(result == 0){//0表示没有编译错误
low = mid + 1;
mid = (low + high)/2;
max = codePointCount;
for (int i = codePointCount; i < mid; i++) {
literal.append(ch);
}
System.out.println("长度" + max
+ "编译成功,增加长度至" + mid);
}else{
//编译错误,说明字面量太长
high = mid - 1;
mid = (low + high)/2;
System.err.println("长度" + codePointCount
+ "编译失败,减少长度至" + mid);
int start = ch.length() == 1? mid : mid *2;
literal.delete(start, literal.length());
}
}
err.close();
System.out.println("最大字面量长度:" + max);
}
}
输出结果:
长度500000编译失败,减少长度至249999
长度249999编译失败,减少长度至124999
长度124999编译失败,减少长度至62499
长度62499编译成功,增加长度至93749
长度93749编译失败,减少长度至78124
长度78124编译失败,减少长度至70311
长度70311编译失败,减少长度至66405
长度66405编译失败,减少长度至64452
长度64452编译成功,增加长度至65428
长度65428编译成功,增加长度至65916
长度65916编译失败,减少长度至65672
长度65672编译失败,减少长度至65550
长度65550编译失败,减少长度至65489
长度65489编译成功,增加长度至65519
长度65519编译成功,增加长度至65534
长度65534编译成功,增加长度至65542
长度65542编译失败,减少长度至65538
长度65538编译失败,减少长度至65536
长度65536编译失败,减少长度至65535
长度65535编译失败,减少长度至65534
最大字面量长度:65534
但是若 修改代码
String ch = "α";
结论 : 最大字面量长度:32767
若 String ch = "字";
最大字面量长度:21845
在class文件中,使用CONSTANT_Utf8_info表来存放各种常量字符串,包括String字面常量,类或接口的全限定名,方法及变量的名称、描述符等。CONSTANT_Utf8_info表的结构如表 所示。
从表3-1可知,CONSTANT_Utf8_info表使用2字节来表示字符串的长度,因此,bytes数组的最大长度为216−1,即65535字节。可是,为什么4个字符(“A”、“á”、“字”与“㊣”)的运行结果各不相同呢?原因在于,在CONSTANT_Utf8_info表中,从“\u0001”~“\u007f”,bytes使用1字节来表示,空字符(null,即“\u0000”)和从“\u0080”~“\u07ff”,使用2字节来表示,从“\u0800”~“\uffff”,使用3字节来表示,而对于增补字符,即代码点范围在“U+10000”~“U+10FFFF”之间的字符,使用6字节来表示。也可以这样认为,增补字符是使用一个代理对来表示的,而代理对的取值范围为“\ud800”~“\udfff”,这些字符都在“\u0800”~“\uffff”之间,每个代理字符使用3字节表示,共6字节。上述的存储是在class文件中的实现,不要与Java程序中的字符相混淆,对于Java程序来说,“A”、“á”、“字”都使用一个char类型变量表示,即2字节,而“[插图]”(增补字符)使用两个char类型变量表示,即4字节。
String字面常量的最大长度与String在内存中的最大长度是不一样的,后者的最大长度为int类型的最大值,即2147483647,而前者根据字符(字符Unicode值)的不同,最大长度也不同,最大长度为65534(可手动修改class文件,令输出结果为65535)。
String字面常量的最大长度是由CONSTANT_Utf8_info表来决定的,该长度在编译时确定,如果超过了CONSTANT_Utf8_info表bytes数组所能表示的上限,就会产生编译错误。
来源:https://blog.csdn.net/qq_27605885/article/details/103684896
猜你喜欢
- 咱们废话不多说进入主题、系统主页展示:用户登录后进行系统首页:主要功能模块如下、分角色管理、超级管理员拥有最高权限、可以进行菜单灵活控制、用
- 在SpringBoot中,当需要获取到配置文件数据时,除了可以用Spring自带的@Value注解外,SpringBoot提供了一种更加方便
- IDEA 2020 源生是不支持中文的,感谢捷克工程师(可能是由国人实现)对我大天朝程序员的“照顾”,且不说这个必要性到底有多大,但从侧面体
- Spring Security中的内置过滤器顺序是怎么维护的?我想很多开发者都对这个问题感兴趣。本篇我和大家一起探讨下这个问题。HttpSe
- timer的schedule和scheduleAtFixedRate方法一般情况下是没什么区别的,只在某个情况出现时会有区别--当前任务没有
- 本文主要给大家介绍java的InputStream 流的使用。(1)FileInputstream: 子类,读取数据的通道使用步骤:1.获取
- 背景在接口请求过程中,传递json对象,springboot转换为实体VO对象后,所有属性都为null。post请求:后台接收请求:当时就懵
- 在spring 3.2 及以后版本中增加了对请求的异步处理,旨在提高请求的处理速度降低服务性能消耗。在我们的请求中做了耗时处理,当并发请求的
- 在前面的文章<Mybatis配置之<properties>属性配置元素详述>,我们讲述了<properties
- 本文实例为大家分享了Android自定义带圆点的半圆形进度条,供大家参考,具体内容如下仅限用于半圆形,如须要带圆点的圆形进度条,圆点会出现错
- 讲这个例子前,咱们先来看一个简单的程序:字符串数组实现数字转字母:#include <stdio.h>#include <
- Spring Security 过滤器链及自定义Filter别名类名称Namespace Element or AttributeCHANN
- 在 Java 中,LinkedList 和 ArrayList 的性能是不同的,具体取决于你所需要的操作。对于频繁的插入和删除操作,Link
- Linux Hadoop 2.7.3 安装搭建Hadoop实现了一个分布式文件系统(Hadoop Distributed File Syst
- 本文主要记录JAVA中对象的初始化过程,包括实例变量的初始化和类变量的初始化以及final关键字对初始化的影响。另外,还讨论了由于继承原因,
- 一、数组创建1.1 声明并赋值int[] a = {1,2,3};1.2 声明数组名开辟空间并且赋值int[] a;a = new int[
- 在本文中,我们将介绍二进制搜索相对于简单线性搜索的优势,并介绍它在 Java 中的实现。1. 需要有效的搜索假设我们在wine-sellin
- 有时候数据库文档需要整理,可是只能手动的复制粘贴,心中一万只草泥马奔腾而过。。。screw简洁好用的数据库表结构文档生成工具。1. 创建项目
- 前言最近有项目需要开发档案打包下载功能,其中包含很多大附件,项目使用minio存储且不在同一台服务器上,为了优化速度决定使用windows共
- Android异常详情介绍这种异常我遇到以下两种情况: 1. java.lang.IllegalStateException: No wra