原文地址:

https://toutiao.io/shares/2029578/url

String是Java中很重要的一个数据类型,除了基本数据类型以外,String是被使用的最广泛的了,但是,关于String,其实还是有很多东西容易被忽略的。

就如本文我们要讨论的问题:Java中的String有没有长度限制?

这个问题要分两个阶段看,分别是编译期和运行期。不同的时期限制不一样。

1

编译期

首先,我们先来合理的推断一下,当我们在代码中使用String s = "";的形式来定义String对象的时候,""中字符的个数有没有限制呢?

既然是合理的推断,那就要要足够的依据,所以我们可以从String的源码入手,根据public String(char value[], int offset, int count)的定义,count是int类型的,所以,char value[]中最多可以保存Integer.MAX_VALUE个,即2147483647字符。(jdk1.8.0_73)

但是,实验证明,String s = "";中,最多可以有65534个字符。如果超过这个个数。就会在编译期报错。

public static void main(String[] args) {

    String s = "a...a";// 共65534个a
System.out.println(s.length()); String s1 = "a...a";// 共65535个a
System.out.println(s1.length());
}

以上代码,会在String s1 = "a…a";// 共65535个a处编译失败:

javac StringLenghDemo.java
StringLenghDemo.java:11: 错误: 常量字符串过长

明明说好的长度限制是2147483647,为什么65535个字符就无法编译了呢?

当我们使用字符串字面量直接定义String的时候,是会把字符串在常量池中存储一份的。那么上面提到的65534其实是常量池的限制。

常量池中的每一种数据项也有自己的类型。Java中的UTF-8编码的Unicode字符串在常量池中以CONSTANT_Utf8类型表示。

CONSTANTUtf8info是一个CONSTANTUtf8类型的常量池数据项,它存储的是一个常量字符串。常量池中的所有字面量几乎都是通过CONSTANTUtf8info描述的。CONSTANTUtf8_info的定义如下

CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
}

由于本文的重点并不是CONSTANTUtf8info的介绍,这里就不详细展开了,我们只需要我们使用字面量定义的字符串在class文件中,是使用CONSTANTUtf8info存储的,而CONSTANTUtf8info中有u2 length;表明了该类型存储数据的长度。

u2是无符号的16位整数,因此理论上允许的的最大长度是2^16=65536。而 java class 文件是使用一种变体UTF-8格式来存放字符的,null 值使用两个 字节来表示,因此只剩下 65536- 2 = 65534个字节。

关于这一点,在the class file format spec中也有明确说明:

The length of field and method names, field and method descriptors, and other constant string values is limited to 65535 characters by the 16-bit unsigned length item of the CONSTANTUtf8info structure (§4.4.7). Note that the limit is on the number of bytes in the encoding and not on the number of encoded characters. UTF-8 encodes some characters using two or three bytes. Thus, strings incorporating multibyte characters are further constrained.

也就是说,在Java中,所有需要保存在常量池中的数据,长度最大不能超过65535,这当然也包括字符串的定义咯。

2

运行期

上面提到的这种String长度的限制是编译期的限制,也就是使用String s= "";这种字面值方式定义的时候才会有的限制。

那么。String在运行期有没有限制呢,答案是有的,就是我们前文提到的那个Integer.MAX_VALUE ,这个值约等于4G,在运行期,如果String的长度超过这个范围,就可能会抛出异常。(在jdk 1.9之前)

int 是一个 32 位变量类型,取正数部分来算的话,他们最长可以有

2^31-1 =2147483647 个 16-bit Unicodecharacter

2147483647 * 16 = 34359738352 位
34359738352 / 8 = 4294967294 (Byte)
4294967294 / 1024 = 4194303.998046875 (KB)
4194303.998046875 / 1024 = 4095.9999980926513671875 (MB)
4095.9999980926513671875 / 1024 = 3.99999999813735485076904296875 (GB)

有近 4G 的容量。

string长度问题的更多相关文章

  1. java String长度与varchar长度匹配理解(字符和字节长度理解)

    java String长度与varchar长度匹配理解(字符和字节长度理解) string中的length()长度,返回的是char的数量,每个char可以存储世界上任何类型的文字和字符,一个char ...

  2. C# 与数据库中字段类型 Int16(short), Int32(int), Int64(long)的取值范围、区别 。string长度

    一开始看到Int16, Int32, Int64这三种类型就觉得有点怪, 为什么要整个数字结尾的, 挺怪的. 昨天互相想到, ms这么干就是想让大家一眼就知道这个数据类型占多大空间吧. Int8, 等 ...

  3. Java int转string 长度不足左补0

    最近项目中用到这个需求,我试了两个方法都可以实现 方法一:(推荐) String s=String.format("%010d", 123)//123为int类型,0代表前面要补的 ...

  4. String长度限制?

    String我们在开发和学习中会经常用到,但对String类型的取值范围我们并不明确. String底层是char数组,并未标明长度限制.java中可以对数组指定长度,如果不指定就以实际元素来指定 p ...

  5. 我说精通字符串,面试官竟然问我 Java 中的 String 有没有长度限制?

    String 是 Java 中很重要的一个数据类型,除了基本数据类型以外,String 是被使用的最广泛的了,但是,关于 String,其实还是有很多东西容易被忽略的. 就如本文我们要讨论的问题:Ja ...

  6. 我说我精通字符串,面试官竟然问我Java中的String有没有长度限制!?|附视频讲解

    关于String有没有长度限制的问题,我之前单独写过一篇文章分析过,最近我又抽空回顾了一下这个问题,发现又有了一些新的认识.于是准备重新整理下这个内容. 这次在之前那篇文章的基础上除了增加了一些验证过 ...

  7. Swift3 - String 字符串、Array 数组、Dictionary 字典的使用

    Swift相关知识,本随笔为 字符串.数组.字典的简单使用,有理解.使用错误的地方望能指正. ///************************************************** ...

  8. string黑科技

    1. string对象的定义和初始化以及读写 string s1; 默认构造函数,s1为空串string s2(s1); 将s2初始化为s1的一个副本string s3("valuee&qu ...

  9. Java总结篇系列:Java String

    String作为Java中最常用的引用类型,相对来说基本上都比较熟悉,无论在平时的编码过程中还是在笔试面试中,String都很受到青睐,然而,在使用String过程中,又有较多需要注意的细节之处. 1 ...

随机推荐

  1. kafka删除topic及其相关数据

    1.删除kafka存储目录(server.properties文件log.dirs配置,默认为"/tmp/kafka-logs")相关topic目录 2.Kafka 删除topic ...

  2. Django框架(十三)——Auth模块

    Auth模块 一.什么是auth模块 Auth模块是Django自带的用户认证模块 Auth模块是Django自带的用户认证模块,可以实现包括用户注册.用户登录.用户认证.注销.修改密码等功能.默认使 ...

  3. C程序编译和执行

    编译 & 执行 C 程序 首先准备一个源码文件 hello.c 键入如下代码: #include <stdio.h> int main() { /* 我的第一个 C 程序 */ p ...

  4. Linux 生成随机mac地址,并固化到本地

    前言: 将Mac地址随机化并固化到本地可以有效避免同一个网络内,mac地址冲突导致的网络阻塞问题. 以下是有关的方法: 1.使用$RANDOM和md5sum(嵌入式无需移植其他软件的优秀可选方案) M ...

  5. BZOJ5312 冒险 势能分析、线段树

    传送门 区间位赋值.区间求最大值似乎是不能够像一般的线段树一样直接打标记的,但是直接暴力也太没有面子了. 我们考虑优化一下暴力:如果说线段树的一段区间内在当前修改的所有位置上所有数都是相同的,那么这个 ...

  6. 矩阵优化DP类问题应用向小结

    前言 本篇强调应用,矩阵的基本知识有所省略(也许会写篇基础向...). 思想及原理 为什么Oier们能够想到用矩阵来加速DP呢?做了一些DP题之后,我们会发现,有时候DP两两状态之间的转移是定向的,也 ...

  7. HTML5+规范:Geolocation(管理设备位置信息) 定位

    Geolocation模块管理设备位置信息,用于获取地理位置信息,如经度.纬度等.通过plus.geolocation可获取设备位置管理对象.虽然W3C已经提供标准API获取位置信息,但在某些平台存在 ...

  8. hystrix中request cache请求缓存

    有一个概念,叫做reqeust context,请求上下文,一般来说,在一个web应用中, 我们会在一个filter里面,对每一个请求都施加一个请求上下文,就是说,tomcat容器内,每一次请求,就是 ...

  9. nmon2influxdb+grafana:服务监控可视化部署

    在工作中,无论是定位线上问题,还是性能优化,都需要对前端.后台服务进行监控.而及时的获取监控数据,能更好的帮助技术人员排查定位问题. 前面的博客介绍过服务端监控工具:Nmon使用方法及利用easyNm ...

  10. navicat连接mysql出现2059

    1.找到mysql的目录:C:\Program Files\MySQL\MySQL Server 8.0\bin 2.清空此目录,输入cmd,回车 3.在控制台输入:mysql -u root -p ...