IDEA 编译报错 “java: 常量字符串过长” 的解决办法

目录

一、问题描述

今天在开发过程中,由于尝试将一个文件的 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 即可。

java 复制代码
public static String getConstant() {
    StringBuilder builder = new StringBuilder();
    builder.append("字符串1");
    builder.append("字符串2");
    // ...
    return builder.toString();
}

解决方案②:读取文件内容

还有一种方式是将字符串写入文件后读出来,如下所示:

java 复制代码
try (BufferedReader reader = new BufferedReader(new FileReader("longString.txt"))) {
    StringBuilder builder = new StringBuilder();
    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

相关推荐
叫致寒吧2 小时前
Tomcat详解
java·tomcat
S***26756 小时前
基于SpringBoot和Leaflet的行政区划地图掩膜效果实战
java·spring boot·后端
马剑威(威哥爱编程)6 小时前
鸿蒙6开发视频播放器的屏幕方向适配问题
java·音视频·harmonyos
JIngJaneIL6 小时前
社区互助|社区交易|基于springboot+vue的社区互助交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·社区互助
V***u4537 小时前
MS SQL Server partition by 函数实战二 编排考场人员
java·服务器·开发语言
这是程序猿7 小时前
基于java的ssm框架旅游在线平台
java·开发语言·spring boot·spring·旅游·旅游在线平台
i***t9197 小时前
基于SpringBoot和PostGIS的云南与缅甸的千里边境线实战
java·spring boot·spring
k***08297 小时前
【监控】spring actuator源码速读
java·spring boot·spring
麦麦鸡腿堡7 小时前
Java_网络编程_InetAddress类与Socket类
java·服务器·网络
vx_dmxq2118 小时前
【PHP考研互助系统】(免费领源码+演示录像)|可做计算机毕设Java、Python、PHP、小程序APP、C#、爬虫大数据、单片机、文案
java·spring boot·mysql·考研·微信小程序·小程序·php