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

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

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

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

01 编译期

首先,我们先来合理的推断一下,当我们在代码中使用 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";

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

          String s1 = "a...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,这当然也包括字符串的定义咯。

02 运行期

上面提到的这种 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)

觉得不错的话就点个好看再走呗~


“不积跬步,无以至千里”,希望未来的你能:有梦为马 随处可栖!加油,少年!

关注公众号:「Java 知己」,每天更新Java知识哦,期待你的到来!

  • 发送「Group」,与 10 万程序员一起进步。
  • 发送「面试」,领取BATJ面试资料、面试视频攻略。
  • 发送「玩转算法」,领取《玩转算法》系列视频教程。
  • 千万不要发送「1024」...

原文地址:https://www.cnblogs.com/java-friend/p/11678317.html

时间: 2024-10-15 12:28:01

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

面试官竟然问我JavaScript中var、let和const有什么区别?

在JavaScript中有三种声明变量的方式:var.let.const. 目录1.var let const1.var(1)var定义的变量在之后可以修改,如果不初始化会输出undefined,不会报错. var a;console.log(a); // undefined// -----------------------------console.log(a); // undefinedvar a = 1;12345(2)var定义的变量,可以跨块访问, 不能跨函数访问. (3)var只有

【深度】扒开V8引擎的源码,我找到了你们想要的前端算法(下次面试官再问算法,用它怼回去!)

算法对于前端工程师来说总有一层神秘色彩,这篇文章通过解读V8源码,带你探索`Array.prototype.sort`函数下的算法实现. 来,先把你用过的和听说过的排序算法都列出来: * 快速排序 * 冒泡排序 * 插入排序 * 归并排序 * 堆排序 * 希尔排序 * 选择排序 * 计数排序 * 桶排序 * 基数排序 * ... 答题环节到了, sort 函数使用的以上哪一种算法? 如果你在网上搜索过关于 sort 源码的文章,可能会告诉你数组长度小于10用插入排序,否则用快速排序. 开始我也是

MVCC和间隙锁,面试官的问法

你在项目中用到事务了吗,如果你对表中的数据进行了两次操作, 1 更新表中的数据 成功 2 删除表中的数据 失败 那么请问 你更新能成功吗. 菜鸡本菜的回答:事务的原子性 导致不会成功. 大佬说(非面试官):这个应该是面试官要问你间隙锁.  通过版本号来标记,不存在删除数据的操作,只是版本号无效. 理论: MVCC和间隙锁 多版本并发控制(Multi-VersionConcurrency Control,Mvcc)是mysql的InnoDb存储引擎实现隔离级别的一种具体的方式, 用于实现读已提交和

如果大厂面试官突然问你FactoryBean+Bean你究竟会多少?

如果大厂面试官突然问你FactoryBean+Bean你究竟会多少? 很多Java程序员都在绞尽脑汁的想要进互联网大厂,那进入大厂必备的条件也是大家最想知道的,有很多大厂在面试的过程中会提一些不那么常见的问题,所以我们在去大厂面试的时候就需要提前做好准备. 如果大厂面试官突然问你FactoryBean+Bean你会怎么回答呢? package com.example.demo10.entity; //实体 public class Stu { String name; public Stu(St

LotusScript提升大字符串拼接函数(功能类似java中StringBuffer)

LotusScript提升大字符串拼接函数(功能类似java中StringBuffer),代码如下: Class StringBuffer Public count As Integer Private arr() As String Private size As Integer Private increment As Integer Sub New(Byval a As Integer) Redim arr(a) increment=a count=0 End Sub Sub add(By

Java中对String字符串的常用操作

这周遇到了一个需要处理String字符串的问题,用到了split将字符串解析为一个String的数组,还用到了某些替换字符的操作. 1 /* 2 **将String source按','间隔开,再分别对array的每个元素进行操作 3 **注意转义的换行符应该是'\\\\n' 4 */ 5 String[] array = source.split("\\,"); 6 7 /* 8 **将所有a替换为b或者删去所有换行符 9 */ 10 source = source.replacea

面试官一问一答的面试题

1,请问你平常用什么浏览器调试? 谷歌,火狐 ,偶尔调试的时候用IE  偶尔会使用下国产的浏览器 问:请说下火狐浏览器,360的浏览器的内核   没听错就是360浏览器 IE浏览器内核:Trident内核,也是俗称的IE内核:Chrome浏览器内核:统称为Chromium内核或Chrome内核,以前是Webkit内核,现在是Blink内核:Firefox浏览器内核:Gecko内核,俗称Firefox内核:Safari浏览器内核:Webkit内核:Opera浏览器内核:最初是自己的Presto内核

面试官再问你 HashMap 底层原理,就把这篇文章甩给他看

前言 HashMap 源码和底层原理在现在面试中是必问的.因此,我们非常有必要搞清楚它的底层实现和思想,才能在面试中对答如流,跟面试官大战三百回合.文章较长,介绍了很多原理性的问题,希望对你有所帮助~ 目录 本篇文章主要包括以下内容: HashMap 的存储结构 常用变量说明,如加载因子等 HashMap 的四个构造函数 tableSizeFor()方法及作用 put()方法详解 hash()方法,以及避免哈希碰撞的原理 resize()扩容机制及原理 get()方法 为什么HashMap链表会

以后面试官再问你三次握手和四次挥手,直接把这一篇文章丢给他

三次握手和四次挥手是各个公司常见的考点,也具有一定的水平区分度,也被一些面试官作为热身题.很多小伙伴说这个问题刚开始回答的挺好,但是后面越回答越冒冷汗,最后就歇菜了. 见过比较典型的面试场景是这样的: 面试官:请介绍下三次握手 求职者:第一次握手就是客户端给服务器端发送一个报文,第二次就是服务器收到报文之后,会应答一个报文给客户端,第三次握手就是客户端收到报文后再给服务器发送一个报文,三次握手就成功了. 面试官:然后呢? 求职者:这就是三次握手的过程,很简单的. 面试官:...... (番外篇: