String字符串的最大长度是多少?
在学习和开发过程中,我们经常会讨论 short ,int 和 long 这些基本数据类型的取值范围,但是对于 String 类型我们好像很少注意它的“取值范围”。那么对于 String 类型,它到底有没有长度限制呢?
其实 String 类型的对象,他们是有长度限制的, String 对象并不能“存储”无限长度的字符串。关于 String 的长度限制要从编译时限制和运行时限制两方面考虑。
编译期限制
有JVM虚拟机相关知识的同学肯定知道,下面定义的字符串常量“自由之路”会被放入方法区的常量池中。
String s = "自由之路";
System.out.println(s);
Stirng 长度之所以会受限制,是因JVM规范对常量池有所限制。常量池中的每一种数据项都有自己的类型。Java中的UTF-8编码的Unicode字符串在常量池中以CONSTANT_Utf8类型表示。
CONSTANT_Utf8的数据结构如下:
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
}
我们重点关注下长度为 length 的那个bytes数组,这个数组就是真正存储常量数据的地方,而 length 就是数组可以存储的最大字节数。length 的类型是u2,u2是无符号的16位整数,因此理论上允许的的最大长度是2^16-1=65535。所以上面byte数组的最大长度可以是65535。
//65535个d,编译报错
String s = "dd..dd";
//65534个d,编译通过
String s1 = "dd..d";
上面的列子中长度为65535的字符串s还是编译失败了,但是长度为65534的字符串 s1 编译是成功的。这个好像和我们刚刚的结论不符合。
其实,这时Javac编译器的额外限制。在Javac的源代码中可以找到以下代码:
private 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;
}
}
代码中可以看出,当参数类型为String,并且长度大于等于65535的时候,就会导致编译失败。
这里需要重点强调下的是:String 的限制并不是对字符串长度的限制,而是对字符串底层存储的限制。这句话可能比较抽象,下面举个列子就清楚了。
Java中的字符常量都是使用UTF8编码的,UTF8编码使用1~4个字节来表示具体的Unicode字符。所以有的字符占用一个字节,而我们平时所用的大部分中文都需要3个字节来存储。
//65534个字母,编译通过
String s1 = "dd..d";
//21845个中文”自“,编译通过
String s2 = "自自...自";
//一个英文字母d加上21845个中文”自“,编译失败
String s3 = "d自自...自";
对于s1,一个字母d的UTF8编码占用一个字节,65534字母占用65534个字节,长度是65534,也没超过Javac的限制,所以可以编译通过。
对于s2,一个中文占用3个字节,21845个正好占用65535个字节,而且字符串长度是21845,并没有超过javac对长度的限制,所以可以编译通过。
对于s3,一个英文字母d加上21845个中文”自“占用65535个字节,超过了最常限制,编译失败。
运行时限制
String 运行时的限制主要体现在 String 的构造函数上。下面是 String 的一个构造函数:
public String(char value[], int offset, int count) {
...
}
上面的count值就是字符串的最大长度。在Java中,int的最大长度是2^31-1。所以在运行时,String 的最大长度是2^31-1。
但是这个也是理论上的长度,实际的长度还要看你JVM的内存。我们来看下,最大的字符串会占用多大的内存。
(2^31-1)*2*16/8/1024/1024/1024 = 4GB
所以在最坏的情况下,一个最大的字符串要占用4GB的内存。如果你的虚拟机不能分配这么多内存的话,会直接报错的。
JDK9以后对String的存储进行了优化。底层不再使用char数组存储字符串,而是使用byte数组。对于LATIN1字符的字符串可以节省一倍的内存空间。
简单总结
String 的长度是有限制的。
- 编译期的限制:字符串的UTF8编码值的字节数不能超过65535,字符串的长度不能超过65534;
- 运行时限制:字符串的长度不能超过2^31-1,占用的内存数不能超过虚拟机能够提供的最大值。
String字符串的最大长度是多少?的更多相关文章
- 关于Java的String字符串常量的长度问题
虽然这种问题应该很难遇到,但是遇到了也会感到莫名其妙.不知道大家有没有遇到那种在java代码里用字符串写sql语句的情况,但是如果sql语句字符串的长度太长的话就会报错. 代码如下: 代码A Stri ...
- linux的string操作(字符串截取,长度计算)
按指定的字符串截取 1.第一种方法: ${varible##*string} 从左向右截取最后一个string后的字符串 ${varible#*string}从左向右截取第一个string后的字符串 ...
- Java的String字符串内容总结
String--字符串 获取字符串的长度 使用Sring类的length()方法可获取字符串对象的长度,例: str.length(); str代表指定的字符串对象;返回值为返回指定字符串的长度.例: ...
- Java String字符串/==和equals区别,str。toCharAt(),getBytes,indexOf过滤存在字符,trim()/String与StringBuffer多线程安全/StringBuilder单线程—— 14.0
课程概要 String 字符串 String字符串常用方法 StringBuffer StringBuilder String字符串: 1.实例化String对象 直接赋值 String str=& ...
- linux shell 字符串操作(长度,查找,替换)详解
linux shell 字符串操作(长度,查找,替换)详解 在做shell批处理程序时候,经常会涉及到字符串相关操作.有很多命令语句,如:awk,sed都可以做字符串各种操作. 其实shell内置一系 ...
- 46. 对称子字符串的最大长度(ToDo)
[题目] 输入一个字符串,输出该字符串中对称的子字符串的最大长度.比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出4. [分析] 可能很多人都写过判断一个字符串 ...
- iOS - Swift String 字符串
前言 public struct String public class NSString : NSObject, NSCopying, NSMutableCopying, NSSecureCodin ...
- 03-Java String字符串详解
1.Java字符串String A.实例化String字符串:直接赋值(更合理一些,使用较多).使用关键字new. B.String内容的比较 // TODO Auto-generated metho ...
- C++学习38 string字符串的增删改查
C++ 提供的 string 类包含了若干实用的成员函数,大大方便了字符串的增加.删除.更改.查询等操作. 插入字符串 insert() 函数可以在 string 字符串中指定的位置插入另一个字符串, ...
随机推荐
- Hello GCN
参考链接: https://www.zhihu.com/question/54504471/answer/611222866 1 拉普拉斯矩阵 参考链接: http://bbs.cvmart.net/ ...
- Weblogic 连接 RMI 服务报错 Connection refused
WebLogic 连接 RMI 服务报错 Connection refused 访问 WebLogic RMI 服务报错,连接被拒绝,连接超时. 奇怪的是,报错的 host 根本不是我要访问的. 报错 ...
- 01-java实现动态数组
01-手撸动态数组 本篇是恋上数据结构第一季个人总结 借鉴https://juejin.im/post/6844904001478066183#heading-0 本人git https://gith ...
- Python学习笔记之 Python设计思想&设计原则
Python设计思想&设计原则 设计思想 1.封装 数据角度 多种数据合为一种数据 优势:代码可读性高 将数据与行为相关联 例如:电脑(内存,储存空间,...) 行为角度 ...
- Qt之先用了再说系列-多线程方式1
Qt 多线程的用法还是比较简单的,也比较好用,接下来我们就分析分析如何使用. 说起Qt 线程的使用方式,一般有2种使用方式,具体哪种比较好看自己心情了,现在有官方的推荐用法,用不用还是看你心情的 好, ...
- C#LeetCode刷题之#118-杨辉三角(Pascal‘s Triangle)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3688 访问. 给定一个非负整数 numRows,生成杨辉三角的前 ...
- doT模板双重循环模板渲染方法
doT模板作为一个前端渲染模板,有着非常显著的有点.1.轻量.2.快捷.3.无依赖. 本文介绍一种几乎所有模板都会遇到的问题,双重循环渲染.我们知道在dot模板中循环渲染用的是{{~ it:value ...
- Redis设计与实现——独立功能的实现
发布和订阅 频道的订阅和退订 struct redisServer{ //键是被订阅者频道 ,键是一个链表,记录所有订阅这个频道的客户端 dict *publish_channels } 订阅实现: ...
- 实战分享丨MySQL 与Django版本匹配相关经验
摘要:关于MySQL 与Django版本匹配相关知识的经验分享. run: (env) E:\PythonPro\PyDjangoProDemo011\xuanyuaniotpro>python ...
- Solon详解(一)- 快速入门
一.Solon 最近号称小而美的的Solon框架,终于得空,搞了一把,发觉Solon确实好用,那Solon到底是什么,又是怎么好用呢? 什么是Solon? Solon参考过Spring boot 和 ...