基础编程学习快乐每一天
首页
留言
Siddim.com
当前位置:
首页
>
编程知识库
>
后端开发知识
>
面试官:String长度有限制吗?是多少?还好我看过
面试官:String长度有限制吗?是多少?还好我看过
阅读
1
2020-11-15
:一年内容,
200
期
Java
面试题阶段汇总
前言
话说
Java
中
String
是有长度限制的,听到这里很多人不禁要问,
String
还有长度限制?是的有,而且在
JVM
编译中还有规范,而且有的家人们在面试的时候也遇到了。
本人就遇到过面试的时候问这个的,而且在之前开发的中也真实地遇到过这个
String
长度限制的场景(将某固定文件转码成
Base64
的形式用字符串存储,在运行时需要的时候在转回来,当时文件比较大),那这个规范限制到底是怎么样的,咱们话不多说先䁖䁖去。
String
首先要知道
String
的长度限制我们就需要知道
String
是怎么存储字符串的,
String
其实是使用的一个
char
类型的数组来存储字符串中的字符的。
存储
String
的容器原来是它
那么
String
既然是数组存储那数组会有长度的限制吗?是的有限制,但是是在有先提条件下的,我们看看
String
中返回
length
的方法。
String
类中的
length
方法
由此我们看到返回值类型是
int
类型,
Java
中定义数组是可以给数组指定长度的,当然不指定的话默认会根据数组元素来指定:
int[] arr1 = new int[10]; // 定义一个长度为10的数组 int[] arr2 = {1,2,3,4,5}; // 那么此时数组的长度为5
整数在
java
中是有限制的,我们通过源码来看看
int
类型对应的包装类
Integer
可以看到,其长度最大限制为
2
^
31
-
1
,那么说明了数组的长度是
0
~
2
^
31
-
1
,那么计算一下就是(
2
^
31
-
1
=
2147483647
=
4GB
)
Integer
的取值范围
看到这我们尝试通过编码来验证一下上述观点。
以字面量形式定义字符串
以上是我通过定义字面量的形式构造的
10
万个字符的字符串,编译之后虚拟机提示报错,说我们的字符串长度过长,不是说好了可以存
21
亿个吗?为什么才
10
万个就报错了呢?
其实这里涉及到了
JVM
编译规范的限制了,其实
JVM
在编译时,如果我们将字符串定义成了字面量的形式,编译时
JVM
是会将其存放在常量池中,这时候
JVM
对这个常量池存储
String
类型做出了限制,接下来我们先看下手册是如何说的。
java
虚拟机规范截图
常量池中,每个
cp
_
info
项的格式必须相同,它们都以一个表示
cp
_
info
类型的单字节 “
tag
”项开头。后面
info
[]项的内容 由
tag
的类型所决定。
java
虚拟机规范手册常量类型表
我们可以看到
String
类型的表示是
CONSTANT
_
String
,我们来看下
CONSTANT
_
String
具体是如何定义的。
这里定义的
u2
string
_
index
表示的是常量池的有效索引,其类型是
CONSTANT
_
Utf8
_
info
结构体表示的,这里我们需要注意的是其中定义的
length
我们看下面这张图。历史文章:
200
期阶段汇总
在
class
文件中
u2
表示的是无符号数占
2
个字节单位,我们知道
1
个字节占
8
位,
2
个字节就是
16
位 ,那么
2
个字节能表示的范围就是
2
^
16
-
1
=
65535
。范中
class
文件格式对
u1
、
u2
的定义的解释做了一下摘要:
这里对
java
虚拟机规摘要部分
1、class文件中文件内容类型解释
定义一组私有数据类型来表示
Class
文件的内容,它们包括
u1
,
u2
和
u4
,分别代 表了
1
、
2
和
4
个字节的无符号数。
每个
Class
文件都是由
8
字节为单位的字节流组成,所有的
16
位、
32
位和
64
位长度的数 据将被构造成
2
个、
4
个和
8
个
8
字节单位来表示。
2、程序异常处理的有效范围解释
start
_
pc
和
end
_
pc
两项的值表明了异常处理器在
code
[]数组中的有效范围。
start
_
pc
必须是对当前
code
[]数组中某一指令的操作码的有效索引,
end
_
pc
要 么是对当前
code
[]数组中某一指令的操作码的有效索引,要么等于
code
_
length
的值,即当前
code
[]数组的长度。
start
_
pc
的值必须比
end
_
pc
小。
当程序计数器在范围[
start
_
pc
,
end
_
pc
)内时,异常处理器就将生效。即设
x
为 异常句柄的有效范围内的值,
x
满足:
start
_
pc
≤
x
&
lt
;
end
_
pc
。
实际上,
end
_
pc
值本身不属于异常处理器的有效范围这点属于
Java
虚拟机历史上 的一个设计缺陷:如果
Java
虚拟机中的一个方法的
code
属性的长度刚好是
65535
个字节,并且以一个
1
个字节长度的指令结束,那么这条指令将不能被异常处理器 所处理。
不过编译器可以通过限制任何方法、实例初始化方法或类初始化方法的
code
[]数组最大长度为
65534
,这样可以间接弥补这个
BUG
。
注意:这里对个人认为比较重要的点做了标记,首先第一个加粗说白了就是说数组有效范围就是【
0
-
65565
】但是第二个加粗的地方又解释了,因为虚拟机还需要
1
个字节的指令作为结束,所以其实真正的有效范围是【
0
-
65564
】,这里要注意这里的范围仅限编译时期,如果你是运行时拼接的字符串是可以超出这个范围的。
接下来我们通过一个小实验来测试一下我们构建一个长度为
65534
的字符串,看看是否就能编译通过。历史文章:
200
期阶段汇总
首先通过一个
for
循环构建
65534
长度的字符串,在控制台打印后,我们通过自己度娘的一个在线字符统计工具计算了一下确实是
65534
个字符,如下:
然后我们将字符复制后以定义字面量的形式赋值给字符串,可以看到我们选择这些字符右下角显示的确实是
65534
,于是乎运行了一波,果然成功了。
看到这里我们来总结一下:
问:字符串有长度限制吗?是多少?
答:首先字符串的内容是由一个字符数组
char
[] 来存储的,由于数组的长度及索引是整数,且
String
类中返回字符串长度的方法
length
() 的返回值也是
int
,所以通过查看
java
源码中的类
Integer
我们可以看到
Integer
的最大范围是
2
^
31
-
1
,由于数组是从
0
开始的,所以数组的最大长度可以使【
0
~
2
^
31
】通过计算是大概
4GB
。
但是通过翻阅
java
虚拟机手册对
class
文件格式的定义以及常量池中对
String
类型的结构体定义我们可以知道对于索引定义了
u2
,就是无符号占
2
个字节,
2
个字节可以表示的最大范围是
2
^
16
-
1
=
65535
。
其实是
65535
,但是由于
JVM
需要
1
个字节表示结束指令,所以这个范围就为
65534
了。超出这个范围在编译时期是会报错的,但是运行时拼接或者赋值的话范围是在整形的最大范围。
解析到这里就告一段落了,如果觉得在下讲得对你有帮助的可以点一波关注,下方的小拇指点一波支持,如果发现有讲的不好的或者有什么遗漏的,欢迎评论区留言相互学习,进步,后期会不定期更新更多的技术编程相关的文章。
END
来源:
www
.
toutiao
.
com
/
i6893014573322863111
十期推荐
【
181
期】
HashMap
面试二十一问!
【
182
期】
SpringCloud
常见面试题(
2020
最新版)
【
183
期】面试官:线上服务平均响应时间太长,怎么排查?
【
184
期】
SQL
数据库面试题以及答案(
50
例题)
【
185
期】面试官:你能说说
Synchronized
实现对象锁的两种方式以及它的原理吗?
【
186
期】一口气说出
Synchronized
同步方法的八种使用场景
【
187
期】出现几率比较大的
Redis
面试题(含答案)
【
188
期】面试官:
delete
、
truncate
、
drop
的区别有哪些,该如何选择
【
189
期】
delete
后加
limit
是个好习惯么
【
190
期】
MQ
消息中间件,面试能问写什么?
? ~
以上数据来源于网络,如有侵权,请联系删除。
上一篇:
设计模式是什么鬼(责任链)
下一篇:
设计模式是什么鬼(观察者)
评论
(0)
提交
类别
基础编程学习
HTML
PHP
Python
编程知识库
后端开发知识
热门文章
Java并发中的同步容器与并发容器,你了解多少?
Innodb中的事务隔离级别和锁的关系,难倒一半面试者!
SpringBoot + minio实现分片上传、秒传、续传
面试官:你知道消息队列如何保证数据不丢失吗?
JAVA知识 Java8新特性
面试官:谈谈为什么要限流,有哪些限流方案?
说说动态代理与静态代理区别
面试官:思考Tomcat 类加载器为什么要违背双亲委派模型?
boot-admin 基于SpringBoot的后台权限管理系统,可作为脚手架,用于快速搭建项目
SpringBoot+Vue+App+硬件实现智能家居系统项目