String 有长度限制吗?是多少?

面试回答

有,编译期和运行期不一样。

编译期需要用 CONSTANT_Utf8_info 结构用于表示字符串常量的值,而这个结构是有长度限制,他的限制是 65535。

运行期,String 的 length 参数 int 类型的,那么也就是说,String 定义的时候,最大支持的长度就是 int 的最大范围值。根据 Integer 类的定义,java.lang.Integer#MAX_VALUE的最大值是 2^31 -1 ;

知识扩展

常量池限制

我们知道,javac 是将文件编译成 class 文件的一个命令,那么在 Class 文件生成过程中,就需要遵守一定的格式。

根据《Java虚拟机规范》中第 4.4 章节常量池的定义,CONSTANT_String_info 用于表示 java.lang.String 类型的常量对象,格式如下:

CONSTANT_String_info{
    u1 tag;
    u2 string_index;
}

其中,string_index 项的值必须是对常量池的有效索引,常量池在该索引处的项必须是 CONSTANT_Utf8_info 结构,表示一组 Unicode 码点序列,这组 Unicode 码点序列最终会被初始化为一个 String 对象。

CONSTANT_Utf8_info 结构用于表示字符串常量的值:

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

其中,length 则指明了 bytes[] 数组的长度,其类型为 u2。

通过翻阅《规范》,我们可以获悉。u2 表示两个字节的无符号数,那么1个字节有8位,2个字节就有16位。

16位无符号数可表示的最大值 2^16 - 1 = 65535。

也就是说,Class 文件中常量池的格式规定了,其字符串常量的长度不能超过 65535。

那么,我们尝试使用以下方式定义字符串:

String s="11111...11111";//其中有 65535 个字符 "1"

尝试使用 javac 编译,同样会得到“java:常量字符串过长”的错误提示,那么原因是什么呢?

其实,这个原因在 javac 的代码中是可以找到的,在 Gen 类中有如下代码:

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 长度的限制是编译期的限制,也就是使用 String s= "" ; 这种字面值方式定义的时候才会有的限制。

那么。String 在运行期有没有限制呢,答案是有的。

String 类中有很多重载的构造函数,其中有几个是支持用户传入 length 来执行长度的:

public String(byte bytes[], int offset, int length) 

可以看到,这里面的参数 length 是使用 int 类型定义的,那么也就是说,String 定义的时候,最大支持的长度就是 int 的最大范围值。

根据 Integer 类的定义,java.lang.Integer#MAX_VALUE的最大值 2^31 - 1;这个值约等于 4G,在运行期,如果 String 的长度超过这个范围,就可能会抛出异常。(在 jdk 1.9 之前)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

协享科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值