目录
一、问题描述
今天在开发过程中,由于尝试将一个文件的
Base64
字符串设置为常量,结果导致 IDEA 编译的时候出现了如下报错:
java: 常量字符串过长
二、问题原因
2.1 理论角度
在 Java 中,常量字符串过长的问题通常是 由于编译器对字符串常量的长度有限制 导致的。
众所周知,Java代码是由
Java编译器(javac)
编译为
class
字节码之后运行的。这个报错就是因为 javac 对字符串常量有一个上线,通常是 65534 个字符串。这个限制是由于 Java 编译器在处理字符串常量时,使用了
16位
的无符号证书来表示字符串的长度,因此最大值为 2^16 - 1 = 65535,但实际使用中会减去一个字符的空间用于其他用途,所以最大长度为 65534。
在 IDEA 中编写代码时,如果定义了一个超过 65534 个字符的字符串常量,编译器就会报错:java: 常量字符串过长。
查看 JVM 规范文档可以看到:在 Java 中,常量 String 的结构体如下:
其中
string_index
指针指向常量池的一个条目,这个条目的结构体格式为
CONSTANT_Utf8_info
。这个结构体的定义如下所示:
- 由上图可知,一个 String 类型的常量的最大长度为
2^16 - 1 = 65535
,但实际使用中会减去一个字符的空间用于其他用途,所以最大长度为 65534。
2.2 源码角度
下面我们再从 javac 源码角度进行分析,源码下载地址:https://jdk.java.net/java-se-ri/8-MR6。
在
\lib\src\jdk.compiler\com\sun\tools\javac\jvm|Gen.java
中可以看到如下代码:
而这个
PoolWriter.MAX_STRING_LENGTH
的值为:
从代码可以看到,要求小于
2^16-1
,所以得出 javac 允许常量 String 保存的最大字节数为 0xFFF-1,即
2^16-1-1=65534
。
三、解决方案
解决方案①:StringBuilder 拼接
我们可以使用
StringBuilder
进行字符串拼接的方式来解决这个问题,只要每次拼接的长度不超过 65534 即可。
publicstaticStringgetConstant(){StringBuilder builder =newStringBuilder();
builder.append("字符串1");
builder.append("字符串2");// ...return builder.toString();}
解决方案②:读取文件内容
还有一种方式是将字符串写入文件后读出来,如下所示:
try(BufferedReader reader =newBufferedReader(newFileReader("longString.txt"))){StringBuilder builder =newStringBuilder();String line;while((line = reader.readLine()!=null)){
builder.append(line);}String longString = builder.toString();}catch(IOException e){
e.printStackTrace();}
除了两种方式,其余几种方式小编亲试均无效:
- 使用加号连接字符串
- 使用换行符
- 使用Eclipse编译器
四、方案验证
我们先创建一个 65535 长度的字符串试一下,结果如下所示,不出意外地报错了:
下面我们去掉一个字符,长度调整为 65534,再次执行,就可以正常打印了,如下图所示:
现在我们已经确定当长度超过 65534 的时候就会报错了,那么我们将长度改为 65535,然后使用
StringBuilder
来实现,结果如下所示:
整理完毕,完结撒花~ 🌻
参考地址:
1.java: 常量字符串过长 报错的解决方法及原因,https://blog.csdn.net/weixin_43957537/article/details/127141232
版权归原作者 不愿放下技术的小赵 所有, 如有侵权,请联系我们删除。