当前位置:首页 > 上门服务 >

未结束的字符串常量怎么解决视频(脚本未结束的字符串常量)

来源:原点资讯(www.yd166.com)时间:2024-01-08 15:42:12作者:YD166手机阅读>>

未结束的字符串常量怎么解决视频,脚本未结束的字符串常量(1)

作者 l Hollis

来源 l Hollis(ID:hollischuang)

关于String有没有长度限制的问题,我之前单独写过一篇文章分析过,最近我又抽空回顾了一下这个问题,发现又有了一些新的认识。于是准备重新整理下这个内容。

这次在之前那篇文章的基础上除了增加了一些验证过程外,还有些错误内容的修正。我这次在分析过程中会尝试对Jdk的编译过程进行debug,并且会参考一些JVM规范等全方面的介绍下这个知识点。因为这个问题涉及到java的编译原理相关的知识,所以通过视频的方式讲解会更加容易理解一些,视频我上传到了B站,大家可以到文末点击阅读原文查看。

未结束的字符串常量怎么解决视频,脚本未结束的字符串常量(2)

String的长度限制

想要搞清楚这个问题,首先我们需要翻阅一下String的源码,看下其中是否有关于长度的限制或者定义。

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

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

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

根据Integer类的定义,Java.lang.Integer#MAX_VALUE的最大值是2^31 - 1;

那么,我们是不是就可以认为String能支持的最大长度就是这个值了呢?

其实并不是,这个值只是在运行期,我们构造String的时候可以支持的一个最大长度,而实际上,在运行期,定义字符串的时候也是有长度限制的。

如以下代码:

String s = "11111...1111";//其中有10万个字符"1"

当我们使用如上形式定义一个字符串的时候,当我们执行javac编译时,是会抛出异常的,提示如下:

错误: 常量字符串过长

那么,明明String的构造函数指定的长度是可以支持2147483647(2^31 - 1)的,为什么像以上形式定义的时候无法编译呢?其实,形如String s = "xxx";定义String的时候,xxx被我们称之为字面量,这种字面量在编译之后会以常量的形式进入到Class常量池。那么问题就来了,因为要进入常量池,就要遵守常量池的有关规定。

未结束的字符串常量怎么解决视频,脚本未结束的字符串常量(3)

常量池限制

我们知道,javac是将Java文件编译成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;

u1 bytes[length];

}

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

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

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

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

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

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

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

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

private void checkStringConstant(DiagnosticPosition var1, Object var2) {

if (this.nerrs == 0 && var2 != && var2 instanceof String

&& ((String)var2).length >= 65535) {

this.log.error(var1, "limit.string", new Object[0]);

this.nerrs;

}

}

代码中可以看出,当参数类型为String,并且长度大于等于65535的时候,就会导致编译失败。

这个地方大家可以尝试着debug一下javac的编译过程(视频中有对java的编译过程进行debug的方法),也可以发现这个地方会报错。

如果我们尝试以65534个字符定义字符串,则会发现可以正常编译。

其实,关于这个值,在《Java虚拟机规范》也有过说明:

If the Java Virtual Machine code for a method is exactly 65535 bytes long and endswith an instruction that is 1 byte long, then that instruction cannot beprotected by an exception handler. A compiler writer can work around this bugby limiting the maximum size of the generated Java Virtual Machine code for anymethod, instance initialization method, or static initializer (the size of anycode array) to 65534 bytes.

未结束的字符串常量怎么解决视频,脚本未结束的字符串常量(4)

运行期限制

上面提到的这种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 的容量。

很多人会有疑惑,编译的时候最大长度都要求小于65535了,运行期怎么会出现大于65535的情况呢。这其实很常见,如以下代码:

String s = "";

for (int i = 0; i <100000 ; i ) {

s ="i";

}

得到的字符串长度就有10万,另外我之前在实际应用中遇到过这个问题。

之前一次系统对接,需要传输高清图片,约定的传输方式是对方将图片转成BASE6编码,我们接收到之后再转成图片。

在将BASE64编码后的内容赋值给字符串的时候就抛了异常。

未结束的字符串常量怎么解决视频,脚本未结束的字符串常量(5)

总结

字符串有长度限制,在编译期,要求字符串常量池中的常量不能超过65535,并且在javac执行过程中控制了最大值为65534。

在运行期,长度不能超过Int的范围,否则会抛异常。

最后,这个知识点 ,我录制了视频,其中有关于如何进行实验测试、如何查阅Java规范以及如何对javac进行debug的技巧。欢迎进一步学习。

未结束的字符串常量怎么解决视频,脚本未结束的字符串常量(6)

☞无代码来了,还要程序员吗?

☞董明珠回应直播带货刷单;腾讯五年 5000 亿发力新基建;Python 3.9 新特性 | 极客头条

☞芯片供应被掐断,华为能否安全渡劫?

☞来了来了!趋势预测算法大PK!

☞Python开发之:Django基于Docker实现Mysql数据库读写分离、集群、主从同步详解 | 原力计划

☞15 岁黑进系统,发挑衅邮件意外获 Offer,不惑之年捐出全部财产,Twitter CEO 太牛了!

栏目热文

字符串和常量对照表(正确的字符串常量有哪些)

字符串和常量对照表(正确的字符串常量有哪些)

在深入学习字符串类之前, 我们先搞懂JVM是怎样处理新生字符串的. 当你知道字符串的初始化细节后, 再去写 String...

2024-01-08 15:17:45查看全文 >>

未结束的字符串常量解决方法教程(字符串常量的正确表示方法)

未结束的字符串常量解决方法教程(字符串常量的正确表示方法)

第二章第六节:字符串常量。下表C语言中的常用转义字符。·字符形式功能:ASCIl码(十进制形式)。→\t水平制表(横向跳...

2024-01-08 15:19:08查看全文 >>

未结束的字符串常量怎么解决(怎么解决未结束的字符串常量)

未结束的字符串常量怎么解决(怎么解决未结束的字符串常量)

字符常量是由一对单撇号括起来的单个字符,如 'a'、'D'、'?'、&...

2024-01-08 15:11:10查看全文 >>

明日之后直楼梯怎么放地板(明日之后弧形楼梯怎么放不了地板)

明日之后直楼梯怎么放地板(明日之后弧形楼梯怎么放不了地板)

明明在巡逻的过程中,总是喜欢观察营地里大佬们的建筑。那么,在营地那么多的建筑中,怎样才能让你的庄园成为最闪亮的星,脱颖而...

2024-01-08 15:41:25查看全文 >>

明日之后房子怎么做旋转楼梯(明日之后旋转楼梯怎么建)

明日之后房子怎么做旋转楼梯(明日之后旋转楼梯怎么建)

今天给大家邀请了来自多贝雪山服务器的建筑大师@虞虞,为大家讲解一下最近很流行,并且超级容易模仿的小猫庄园的设计。一起来看...

2024-01-08 15:37:14查看全文 >>

字符串常量的长度怎么判断(正确的字符串常量怎么判断)

字符串常量的长度怎么判断(正确的字符串常量怎么判断)

作者 l Hollis 来源 l Hollis关于String有没有长度限制的问题,我之前单独写过一篇文章分析过,最近我...

2024-01-08 14:54:40查看全文 >>

字符串常量长度怎样判断(怎么求字符串常量的长度)

字符串常量长度怎样判断(怎么求字符串常量的长度)

在C语言中,字符串是一种常见的数据类型,用于存储文本和字符序列。字符串大小和长度是在处理字符串时经常遇到的问题。然而,由...

2024-01-08 15:15:39查看全文 >>

我的世界螺旋箭指令(我的世界自动弓指令)

我的世界螺旋箭指令(我的世界自动弓指令)

螺旋线是一圈一圈往Z方向延伸,涡状线是往四周延伸,在这里介绍下螺旋线,螺旋线应用广泛,比如“瓶口螺纹”,“螺母”,“螺丝...

2024-01-08 15:04:43查看全文 >>

我的世界指令如何获得箭(我的世界指令手机版大全)

我的世界指令如何获得箭(我的世界指令手机版大全)

大家好,我是游你网的小仙女。《我的世界》中,弓箭是一类很便捷远程的武器,但是威力上并不是很出彩。如果射出去箭能爆炸,那将...

2024-01-08 15:36:39查看全文 >>

nba2k14怎么获得高顺位(NBA2k14电脑版选秀怎么跳过)

nba2k14怎么获得高顺位(NBA2k14电脑版选秀怎么跳过)

NBA2K14算是这款篮球游戏最后一次以平易近人的姿态进入玩家的视野了,因为下一代的2K15直接将容量从7G暴涨至40多...

2024-01-08 15:12:25查看全文 >>

文档排行