检测字符串长度工具(http://tool.huixiang360.com/str/length.php)
2、缘故原由剖析
1、通过源码剖析String该当是由char类型的数组构成
2、如果是char类型的数组那么没有其它限定的情形下String的长度该当为value字符串数组的长度
3、value字符串数组的长度为int类型,那么根据int类型的包装类Integer可以得到如下信息,最大值为2^31-1 但是根据场景仿照结果,显然长度根本没有到2^31-1 就报错了!
!
!
4、这个时候就必须推出JVM,JVM编译时会将字符串转换为字面量,在编译时将字面量放入常量池中,这时候JVM对字符串会做一些限定
参考Java虚拟机规则https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.10
所有的常量池的通用规则如下
字符串的规则如下(这里定义的 u2 string_index 表示的是常量池的有效索引,其类型是CONSTANT_Utf8_info 构造体表示的)
那么什么是CONSTANT_Utf8_info规则
在class文件中u2表示的是无符号数占2个字节单位,我们知道1个字节占8位,2个字节便是16位 ,那么2个字节能表示的范围便是2^16- 1 = 65535(定义一组私有数据类型来表示 Class 文件的内容,它们包括 u1,u2 和 u4,分别代表了1、2 和 4 个字节的无符号数 每个 Class 文件都是由 8 字节为单位的字节流组成,所有的 16 位、32 位和 64 位长度的数 据将被布局成 2 个、4 个和 8 个 8 字节单位来表示)
5、综上可以确定字符串的长度是2^16-1了吗?不不不
根据官方阐明,便是说数组的有效范围是【0-65535】,但是虚拟机还须要一个字节的指令作为结束符,所有真正有效范围是【0-65534】
把稳点:这里的范围仅限编译期间,如果你是运行时拼接的字符串是可以超出这个范围的
// 也便是说如下情形,编译不报错,运行时拼接字符串是可以超过这个范围public class StringTest { public static void main(String[] args) { String result = ""; for (int i = 0; i <1000_0000_00 ; i++) { result+=i; } }}
3、测试
准备字符为65534的字符串,验证通过
4、结论
通过对字符串的源码剖析可知,字符串由字符数据char[ ]构成,由于数组的长度为int类型,而int的包装类是Integer,那么Integer最大的表示值该当为2^31-1, 但是通过翻阅java虚拟机手册可知,class文件格式的定义以及常量池中对String类型的构造体定义我们可以知道对付索引定义了u2,便是无符号占2个字节,2个字节可以表示的最大范围是2^16 -1 = 65535,但虚拟机须要末了一位为结束指令,以是这个范围便是65534。