java String 长度有限制吗?
引言
今天读了一篇关于 java 中 String 长度限制的文章。读完之后,感觉更懵。所以就想自己总结一下这个问题,本文以 jdk1.8 为例进行分析,加深理解。
String 长度有限制
我用标题回答这个问题。这个长度主要分为编译期限制和运行期限制。
编译期限制
JVM 在编译中有自己的规范,String 类型的字面量存储在 JVM 字符串常量池中。CONSTANT_String_info 用于表示 java.lang.String 类型的常量对象,格式如下:
tag: 常量类型->CONSTANT_String(8 字节)
string_index:表示常量池的有效索引,其结构为 CONSUTANT_Utf8_info。表示一组 Unicode 码点序列,通过这组码点序列最终被初始化为一个 String 对象。
这样就很好分析,String 在编译期的限制就是 length 的长度。u2 表示无符号位 2 个单字节的长度,一个字节占 8 位,则 u2(11111111 11111111)表示的范围为 0~2^16-1。那么其范围是[0~65535]。接下来我们进行测试,结论是否正确。
进行编译运行,结果却是:
发现编译过程中竟然报错了,我们继续往下探究。编译是由 javac 进行编译的,感兴趣的小伙伴可自行下载 javac 的源码包http://hg.openjdk.java.net/jdk8/jdk8/langtools/。其中有两段代码,这样写道
Pool.MAX_STRING_LENGTH 的长度究竟是多少,继续往下看
经过 Pool.MAX_STRING_LENGTH 为 0xFFFF 转化成 65535,因为要小于它,所以 length 的最大长度为 65534。进行测试
在开发过程中,有时确实需要复制一大段字符串进行测试。但是往往会编译失败,其原因就是我们使用的是默认的编译期 javac,如何解决呢?以 idea 举例说明。File->Settings,搜索 java Compiler
选择 Eclipse,点击 Apply。这样,我们就将编译器设置为 JDT,JDT 优化为了 StringBuilder 的 append 的方式。
运行时限制
运行时限制就相对简单一些了,查看 String 源码即可找出答案。
String 的长度用 int 类型表示,int 占四个字节,就是 32 位,其长度为 2^31-1,约等于 4GB。
总结
java 中的字符串常量,编译期是 javac 的话,其最大长度为 65534。换句话说,JVM 虚拟机中的字符串常量池,一个 String 对象最多存 65534 字符。
java 运行期间,String 的最大长度为 4GB,这时 String 对象在堆中存放。
Eclipse 有自己的 java 编译器,JDT 优化为了 StringBuilder 的 append。StringBuilder 在 toString 的过程中,相当于重新 new 了一个 String 对象,存放在堆中。
第四点借用下面的引用
Eclise 使用自己的编译器。主要原因是 JDT 核心具有渐进式编译的能力,这意味着它会逐步编译代码中的更改(这也是 Eclipse 不需要编译按钮的原因,因为它会在检测到更改时自动编译)。但 Oracle 的 JDK 不支持增量编译
参考
字符串 String 的最大长度https://segmentfault.com/a/1190000020381075
字符串字面量长度是有限制的https://since1986.github.io/d91c2205.html
版权声明: 本文为 InfoQ 作者【ddww】的原创文章。
原文链接:【http://xie.infoq.cn/article/b984b8c074b658fe2bd868faf】。文章转载请联系作者。
评论 (1 条评论)