对于字符串可以承受的最大长度,要分为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类型长度限制问题相关推荐

  1. String类型长度最多是多少?有限制吗?

    前言 话说Java中String是有长度限制的,听到这里很多人不禁要问,String还有长度限制?是的有,而且在JVM编译中还有规范,而且有的家人们在面试的时候也遇到了. 本人就遇到过面试的时候问这个 ...

  2. String类型的字符长度(码点/代码单元的区别)

    查看String的源码可以发现它以一个char类型的数组保存字符串的,而String.length()方法返回的也是这个char数组的长度. 那么,这个长度和"字符"长度有什么关系 ...

  3. Java String类型数据的字节长度

    问题描述: 向Oracle数据库中一varchar2(64)类型字段中插入一条String类型数据,程序使用String.length()来进行数据的长度校验,如果数据是纯英文,没有问题,但是如果数据 ...

  4. C++中求string类型字符串的长度的方法

    在代码中经常会求字符串的有效长度,对char型字符串数组大家会用strlen来求它的有效长度,如何求string类型字符串的有效长度呢?这里有三种方法. (1)使用string的成员函数length( ...

  5. java string类型大小_Java String类型数据的字节长度

    问题描述: 向Oracle数据库中一varchar2(64)类型字段中插入一条String类型数据,程序使用String.length()来进行数据的长度校 验,如果数据是纯英文,没有问题,但是如果数 ...

  6. js获取int类型长度_js代码比较大小前需要把string转换int

    今天在写代码时发现一个容易忽略的问题,写下来以供参考 这是做的一个验证,设置的最小值minValue不能小于参数本身的最小值min 当输入正数的时候都没有问题,但是输入负数时就出现问题了 正确设置参数 ...

  7. Redis 笔记(03)— string类型(设置key、获取key、设置过期时间、批量设置获取key、对key进行加减、对key值进行追加、获取value子串)

    字符串 string 是 Redis 最简单的数据结构.Redis 所有的数据结构都是以唯一的 key 字符串作为名称,然后通过这个唯一 key 值来获取相应的 value 数据.不同类型的数据结构的 ...

  8. 【delphi】Byte数组与String类型的转换

    string string = AnsiString = 长字符串,理论上长度不受限制,但其实受限于最大寻址范围2的32次方=4G字节: 变量Str名字是一个指针,指向位于堆内存的字符序列,字符序列起 ...

  9. Redis初学:5(String类型的基本操作)

    String类型 String类型是Redis中最基本的类型,String类型有以下的一些特点: String类型是二进制安全的,这意味着String类型可以包含任何的数据,如:图片.序列化的对象等: ...

最新文章

  1. Python 之 Pandas (三)选择数据
  2. 如何一次关闭所有打开的标签?
  3. 融资2.75亿美元的老牌AR公司,倒了
  4. finite state machine drawer online
  5. 关于内存流与字符串的转换
  6. .NET Core 1.1 Preview 1上线:支持macOS 10.12/Linux Mint 18
  7. android 动态修改菜单,如何在Android的“选项”菜单上更改MenuItem?
  8. python中setpos_如何用类初始化Python中的多个turtle
  9. python实现单例模式方法_Python实现单例模式的5种方式
  10. 14-win10下ElasticSearch.6.1.0与head、Kibana、X-Pack、SQL、IK、PINYIN插件的配置安装
  11. Kubernetes入门培训(内含PPT)-(转)
  12. 是否可以在git中预览藏匿内容?
  13. 使用phppgadmin 遇到的小问题
  14. 没有人更比他懂基金业务:博格和他的先锋集团创业史(4):
  15. PYTHON Image Module中Pix[x,y]详解
  16. BP神经网络算法原理
  17. 脉冲触发器(又叫主从触发器)和边沿触发器的区别(三个周期波形图解惑)
  18. 微信公众号开发--自定义菜单跳转页面并获取用户信息
  19. css实现3D动画效果——正方体变六边形
  20. c语言里10h代表什么,汇编中的10H中断int 10h详细说明

热门文章

  1. 第6课 《修改病句》
  2. java图表库_美丽的Java图表类库
  3. 2023年全国最新安全员精选真题及答案49
  4. Python爬虫:爬取西刺代理数据,讲解处理反爬措施(上篇)
  5. CentOS上Docker的安装卸载及Docker简介
  6. 通过IDEA使用GIt
  7. x8086千行汇编项目——汇编贪吃蛇、画图、两个程序的调度
  8. 【数据结构基础】指向函数的指针
  9. 义务教育和医疗保险,不同规则的个人分析
  10. AcWing 4492. 减法操作(AcWing杯 - 周赛)