String类型长度限制问题
对于字符串可以承受的最大长度,要分为2个阶段,一个是编译时期(也就是你代码定义了一个String字符串,String s= “xiaofang”),一个是运行时期(指在程序运行过程中)
编译期String字符串的限制
我们都知道JVM里面是包含常量池的,(是一种对字符串的性能优化,不用反复创建新的字符串了)当我们使用字符串字面量直接定义String的时候,是会把字符串在常量池中存储一份的。常量池中的每一项常量都是一个表,都有自己对应的类型。Java中的UTF-8编码的Unicode字符串在常量池中以CONSTANT_Utf8_info类型表,结构如下:
CopyCONSTANT_Utf8_info {u1 tag;u2 length;u1 bytes[length];
}
u2类型的length的值就表明了这个UTF-8编码字符串长度是多少字节。所以CONSTANT_Utf8_info型常量对应的最大长度也就是java中UTF-8编码的字符串的长度,顺便提一下Class文件中的方法和字段也是引用CONSTANT_Utf8_info型常量来描述名称的。u2是无符号的16位整数,因此理论上允许的的最大长度是2^16-1=65535
我们重点关注下长度为 length 的那个bytes数组,这个数组就是真正存储常量数据的地方,而 length 就是数组可以存储的最大字节数。length 的类型是u2,u2是无符号的16位整数,因此理论上允许的的最大长度是2^16-1=65535。所以上面byte数组的最大长度可以是65535。
编译器javac下String的长度
创建一个测试类
public class TestStr { public static void main(String[] args) { String LongStr ="aaaa...";//一共65535个a System.out.println(LongStr.length()); }}
使用javac命令编译它。编译报错。相应目录没有生成对应的TestStr.class文件
去除一个字符串,使用65534个字符串。
public class TestStr { public static void main(String[] args) { String LongStr ="aaaa...";//一共65534个a System.out.println(LongStr.length()); }}
javac命令编译它。编译正常。相应目录生成对应的TestStr.class文件
我们在看看Oracle JDK的编译工具Javac内部,javac也是java写的。
Copyprivate void checkStringConstant(DiagnosticPosition var1, Object var2) {if (this.nerrs == 0 && var2 != null && var2 instanceof String && ((String)var2).length() >= 65535) {this.log.error(var1, "limit.string", new Object[0]);++this.nerrs;}}
虽然U2类型能表达的最大值是65535。但是在编译时会受到编译器的限制,上面65535个长度的字符串在javac下报错了就是受到了javac编译器的限制了。如果你在上面65534长度生成的TestStr.class中手动在添加一个字符串(注意是在javac编译后的class文件中添加)是可以得到65535长度的结果。
总结一下:在Javac编译器下,字符串String的最大长度限制也即是U2类型所能表达的最大长度65534。避开javac最大长度是65535?
Eclise的JDT编译器下String的长度
Eclipse有自己的Java编译器,称为[JDT Core] [2](org.eclipse.jdt.core)。并不是用的javac编译器。
创建一个测试类
发现Eclipse执行可正常执行。同样的代码在IDEA中是会报错的。
这是因为Eclise的JDT编译器问题。在Eclipse工作空间下找到其编译生成的TestStr.class。使用javap命令查看
6: invokespecial #20; //Method java/lang/StringBuilder."<init>":(Ljava/la
ng/String;)V9: ldc #23; //String QyNDAbAgIGqQIBAQ111: invokevirtual #25; //Method java/lang/StringBuilder.append:(Ljava/lang
/String;)Ljava/lang/StringBuilder;14: invokevirtual #29; //Method java/lang/StringBuilder.toString:()Ljava/l
ang/String;17: invokevirtual #33; //Method java/lang/String.intern:()Ljava/lang/Strin
g;20: astore_121: getstatic #38; //Field java/lang/System.out:Ljava/io/PrintStream;24: aload_125: invokevirtual #44; //Method java/lang/String.length:()I28: invokevirtual #48; //Method java/io/PrintStream.println:(I)V31: return}
上面我们就明白了之所以JDT能编译过,只是因为JDT优化为了StringBuilder的append。
Eclipse编译器本身包含在org.eclipse.jdt.core插件中。Eclipse不会使用任何用户安装的JDK。相反,由于以下主要原因,它使用自己的JDT核心来编译Java程序:
主要原因是JDT核心具有渐进式编译的能力,这意味着它会逐步编译代码中的更改(这也是Eclipse不需要编译按钮的原因,因为它会在检测到更改时自动编译)。但Oracle的JDK不支持增量编译。
运行期String的字符串限制
String内部是以char数组的形式存储,数组的长度是int类型,那么String允许的最大长度就是Integer.MAX_VALUE了。又由于java中的字符是以16位存储的,因此大概需要4GB的内存才能存储最大长度的字符串。
总结一下
1.Java中的字符串String最大长度,编译期如果是javac编译就是65534。如果绕过javac编译的限制,其最大长度可以达到u2类型变达的最大值65535。
2.Java中的字符串String最大长度运行期大约4G。
3.Eclise编译超过65534长度的字符串不报错,是Eclipse有自己的Java编译器。JDT优化为了StringBuilder的append。
4.Eclise使用自己的编译器。主要原因是JDT核心具有渐进式编译的能力,这意味着它会逐步编译代码中的更改(这也是Eclipse不需要编译按钮的原因,因为它会在检测到更改时自动编译)。但Oracle的JDK不支持增量编译。
4.Eclise使用自己的编译器。主要原因是JDT核心具有渐进式编译的能力,这意味着它会逐步编译代码中的更改(这也是Eclipse不需要编译按钮的原因,因为它会在检测到更改时自动编译)。但Oracle的JDK不支持增量编译。
String类型长度限制问题相关推荐
- String类型长度最多是多少?有限制吗?
前言 话说Java中String是有长度限制的,听到这里很多人不禁要问,String还有长度限制?是的有,而且在JVM编译中还有规范,而且有的家人们在面试的时候也遇到了. 本人就遇到过面试的时候问这个 ...
- String类型的字符长度(码点/代码单元的区别)
查看String的源码可以发现它以一个char类型的数组保存字符串的,而String.length()方法返回的也是这个char数组的长度. 那么,这个长度和"字符"长度有什么关系 ...
- Java String类型数据的字节长度
问题描述: 向Oracle数据库中一varchar2(64)类型字段中插入一条String类型数据,程序使用String.length()来进行数据的长度校验,如果数据是纯英文,没有问题,但是如果数据 ...
- C++中求string类型字符串的长度的方法
在代码中经常会求字符串的有效长度,对char型字符串数组大家会用strlen来求它的有效长度,如何求string类型字符串的有效长度呢?这里有三种方法. (1)使用string的成员函数length( ...
- java string类型大小_Java String类型数据的字节长度
问题描述: 向Oracle数据库中一varchar2(64)类型字段中插入一条String类型数据,程序使用String.length()来进行数据的长度校 验,如果数据是纯英文,没有问题,但是如果数 ...
- js获取int类型长度_js代码比较大小前需要把string转换int
今天在写代码时发现一个容易忽略的问题,写下来以供参考 这是做的一个验证,设置的最小值minValue不能小于参数本身的最小值min 当输入正数的时候都没有问题,但是输入负数时就出现问题了 正确设置参数 ...
- Redis 笔记(03)— string类型(设置key、获取key、设置过期时间、批量设置获取key、对key进行加减、对key值进行追加、获取value子串)
字符串 string 是 Redis 最简单的数据结构.Redis 所有的数据结构都是以唯一的 key 字符串作为名称,然后通过这个唯一 key 值来获取相应的 value 数据.不同类型的数据结构的 ...
- 【delphi】Byte数组与String类型的转换
string string = AnsiString = 长字符串,理论上长度不受限制,但其实受限于最大寻址范围2的32次方=4G字节: 变量Str名字是一个指针,指向位于堆内存的字符序列,字符序列起 ...
- Redis初学:5(String类型的基本操作)
String类型 String类型是Redis中最基本的类型,String类型有以下的一些特点: String类型是二进制安全的,这意味着String类型可以包含任何的数据,如:图片.序列化的对象等: ...
最新文章
- Python 之 Pandas (三)选择数据
- 如何一次关闭所有打开的标签?
- 融资2.75亿美元的老牌AR公司,倒了
- finite state machine drawer online
- 关于内存流与字符串的转换
- .NET Core 1.1 Preview 1上线:支持macOS 10.12/Linux Mint 18
- android 动态修改菜单,如何在Android的“选项”菜单上更改MenuItem?
- python中setpos_如何用类初始化Python中的多个turtle
- python实现单例模式方法_Python实现单例模式的5种方式
- 14-win10下ElasticSearch.6.1.0与head、Kibana、X-Pack、SQL、IK、PINYIN插件的配置安装
- Kubernetes入门培训(内含PPT)-(转)
- 是否可以在git中预览藏匿内容?
- 使用phppgadmin 遇到的小问题
- 没有人更比他懂基金业务:博格和他的先锋集团创业史(4):
- PYTHON Image Module中Pix[x,y]详解
- BP神经网络算法原理
- 脉冲触发器(又叫主从触发器)和边沿触发器的区别(三个周期波形图解惑)
- 微信公众号开发--自定义菜单跳转页面并获取用户信息
- css实现3D动画效果——正方体变六边形
- c语言里10h代表什么,汇编中的10H中断int 10h详细说明