开篇三个问题

作为Java的程序员,不知道在Java代码中定义了多少个字符串,可是看看下面3个问题。你是否认真思考过?是否动手实践过?

1.Java中的字符串String的最大长度是多少?

2.Eclipse使用哪种Java编译器?

3.为何Eclipse要出自己的编译器?

对于字符串可以承受的最大长度,要分为2个阶段,一个是编译时期(也就是你代码定义了一个String字符串,String s= "xiaohu"),一个是运行时期(指在程序运行过程中)

编译期String字符串的限制

我们都知道JVM里面是包含常量池的,(是一种对字符串的性能优化,不用反复创建新的字符串了)当我们使用字符串字面量直接定义String的时候,是会把字符串在常量池中存储一份的。常量池中的每一项常量都是一个表,都有自己对应的类型。Java中的UTF-8编码的Unicode字符串在常量池中以CONSTANT_Utf8_info类型表,结构如下:

CONSTANT_Utf8_info型常量的结构

类型

名称

数量

u1

tag

1

u2

length

1

u1

bytes

length

u2类型的length的值就表明了这个UTF-8编码字符串长度是多少字节。所以CONSTANT_Utf8_info型常量对应的最大长度也就是java中UTF-8编码的字符串的长度,顺便提一下Class文件中的方法和字段也是引用CONSTANT_Utf8_info型常量来描述名称的。u2是无符号的16位整数,因此理论上允许的的最大长度是2^16-1=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写的。

/** Check a constant value and report if it is a string that is

* too large.

*/

private void checkStringConstant(DiagnosticPosition pos, Object constValue) {

if (nerrs != 0 || // only complain about a long string once

constValue == null ||

!(constValue instanceof String) ||

((String)constValue).length() < Pool.MAX_STRING_LENGTH)

return;

log.error(pos, "limit.string");

nerrs++;

}

...

在看看Pool.MAX_STRING_LENGTH

public class Pool {

...

public static final int MAX_STRING_LENGTH = 0xFFFF;

...

}

通过上边代码可以看到 MAX_STRING_LENGTH = 0xFFFF 而 0xFFFF 是十进制的 65535。但是上面我们得出的结果是Javac编译下最大长度是65534,是因为 Javac 源码中做的限制是((String)constValue).length() < Pool.MAX_STRING_LENGTH) 注意是 < 而不是 <= , 小于65535那自然最多只能是65534了。

但是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编译器。

创建一个测试类

public class TestStr {

public static void main(String[] args) {

String LongStr ="aaaa..."//一共65540个a

System.out.println(LongStr.length());

}

}

发现Eclipse执行可正常执行。这肯定是Eclise的JDT编译器做了手脚。果然通过在Eclipse工作空间下找到了其编译生成的TestStr.class。使用javap命令查看

6: invokespecial #20; //Method java/lang/StringBuilder."":(Ljava/la

ng/String;)V

9: ldc #23; //String QyNDAbAgIGqQIBAQ1

11: 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_1

21: getstatic #38; //Field java/lang/System.out:Ljava/io/PrintStream;

24: aload_1

25: invokevirtual #44; //Method java/lang/String.length:()I

28: invokevirtual #48; //Method java/io/PrintStream.println:(I)V

31: 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不支持增量编译。

若本文对你有用,有任何疑问,欢迎关注我。

python字符串最大长度_字符串String的最大长度相关推荐

  1. python给定字符串显示奇数_字符串基础练习题80+道(原文及代码见文尾链接)

    Python 字符串基础练习题80+道 1.编写一个Python程序来计算字符串的长度. 2.编写一个Python程序来计算字符串中的字符数(字符频率). Sample String:google.c ...

  2. java字符串替换空格符_字符串替换空格

    题目描述 请实现一个函数,将一个字符串中的每个空格替换成"%20".例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 解题思路 ...

  3. linuxsed替换字符串后保存_字符串方法——replace()

    1.字符串方法-- replace() str.replace(old, new[,max]) 参数说明(Parameters) old:被替换的字符串 new:新字符串,替换原来的old字符串 ma ...

  4. c语言字符串子串查找_字符串操作的全面总结

    来自公众号:C语言与cpp编程 字符串操作看似简单,其实非常重要,不注意的话,经常出现代码运行结果和自己想要的不一致,甚至崩溃.本文总结了一些构建string对象方法.修改string对象的方法.st ...

  5. java 字符串 字节数组_字符串到字节数组,字节数组到Java中的字符串

    java 字符串 字节数组 Today we will learn how to convert String to byte array in java. We will also learn ho ...

  6. java 字符串数组定义_「string数组」string 数组怎么定义 - seo实验室

    string数组 string数组的定义有三种: String arr[] = new String[10]; //创建一个长度为10的String 类型数组. String arr[] = {&qu ...

  7. Java 字符串数组定义_「string数组」string 数组怎么定义

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到网站 点击跳转浏览. string数组的定义有三种: String arr[] = new String[1 ...

  8. python字符串的特点_字符串特点_清华尹成python入门教程_少儿编程视频-51CTO学院...

    此课程与<清华编程高手.尹成.带你实战python入门>大体相同,只需购买其中的一门课程. 本课程由清华大学尹成老师录制,课程的特色在于讲解原理的同时引入了每个程序员都热衷的黑客技术.py ...

  9. spring字符串判空_字符串工具类StringUtils实现字符串是否中文、字符串分割/判空/替换/查找、是否包含乱码及字符串数组合并等常规操作...

    一.前言 关于字符串工具类StringUtils实现字符串是否包含isChinese中文.是否包含isMessyCode乱码.常规数据类型转换.替换/删除/判空.两字符串数组mergeStringAr ...

最新文章

  1. Elasticsearch入门和基本使用
  2. Redis资料汇总专题
  3. java jml_JML 入门
  4. python情感分析算法_Python 情感分析
  5. 一个简单的数据库工具类
  6. DECLARE_DYNAMIC IMPLEMENT_DYNAMIC
  7. Intel 8042键盘控制器详细介绍
  8. 【图解】FFmpeg播放器基本原理
  9. CefSharp 知道这些就完事了
  10. shell编程三大神器之grep
  11. [样本分析] 海莲花CS样本
  12. Base64的编码以及解码
  13. SAP系统开发里程碑 2022 刘欣
  14. uniApp 生命周期【应用生命周期 和 页面生命周期】
  15. ECB oracle——attack
  16. links for myself
  17. 查询MySQL数据库中所有表的结构
  18. 微量齿轮泵mzr-7245和mzr-4622在全自动密度测定中的应用
  19. 刘军荣电商培训——电商成长之路
  20. eps罗马柱头制作方法_马鞍山EPS屋檐线条安装方案,EPS罗马柱

热门文章

  1. python省市区三级联动_Ajax实现省市区三级级联详解
  2. linux下c 指针变量大小,C语言sizeof关键字
  3. [译]JavaScript的新功能将改变正则表达式的编写方式
  4. KubeCon+CloudNativeCon首登中国,时速云受邀发表主题演讲
  5. Spring boot中使用aop详解
  6. Linux Linux常用命令二
  7. Android圆角图片封装类--copy别人的,不能转载,我也就醉了,谢谢原创
  8. IOS UI Automation 学习之常用类,方法和模拟手势
  9. Linux内核学习笔记五——中断推后处理机制
  10. BIND9之dig工具的使用方法