Java字符串池(String Pool)深度解析

在工作中,String类是我们使用频率非常高的一种对象类型。JVM为了提升性能和减少内存开销,避免字符串的重复创建,其维护了一块特殊的内存空间,这就是我们今天要讨论的核心,即字符串池(String Pool)。字符串池由String类私有的维护。

我们知道,在Java中有两种创建字符串对象的方式:1)采用字面值的方式赋值 2)采用new关键字新建一个字符串对象。这两种方式在性能和内存占用方面存在着差别。

方式一:采用字面值的方式赋值,例如:

img

采用字面值的方式创建一个字符串时,JVM首先会去字符串池中查找是否存在"aaa"这个对象,如果不存在,则在字符串池中创建"aaa"这个对象,然后将池中"aaa"这个对象的引用地址返回给字符串常量str,这样str会指向池中"aaa"这个字符串对象;如果存在,则不创建任何对象,直接将池中"aaa"这个对象的地址返回,赋给字符串常量。

在本例中,执行:str == str2 ,会得到以下结果:

img

这是因为,创建字符串对象str2时,字符串池中已经存在"aaa"这个对象,直接把对象"aaa"的引用地址返回给str2,这样str2指向了池中"aaa"这个对象,也就是说str和str2指向了同一个对象,因此语句System.out.println(str == str2)输出:true。

方式二:采用new关键字新建一个字符串对象,例如:

img

采用new关键字新建一个字符串对象时,JVM首先在字符串池中查找有没有"aaa"这个字符串对象,如果有,则不在池中再去创建"aaa"这个对象了,直接在堆中创建一个"aaa"字符串对象,然后将堆中的这个"aaa"对象的地址返回赋给引用str3,这样,str3就指向了堆中创建的这个"aaa"字符串对象;如果没有,则首先在字符串池中创建一个"aaa"字符串对象,然后再在堆中创建一个"aaa"字符串对象,然后将堆中这个"aaa"字符串对象的地址返回赋给str3引用,这样,str3指向了堆中创建的这个"aaa"字符串对象。

在这个例子中,执行:str3 == str4,得到以下结果:

img

因为,采用new关键字创建对象时,每次new出来的都是一个新的对象,也即是说引用str3和str4指向的是两个不同的对象,因此语句System.out.println(str3 == str4)输出:false。

字符串池的实现有一个前提条件:String对象是不可变的。因为这样可以保证多个引用可以同事指向字符串池中的同一个对象。如果字符串是可变的,那么一个引用操作改变了对象的值,对其他引用会有影响,这样显然是不合理的。

字符串池的优缺点:字符串池的优点就是避免了相同内容的字符串的创建,节省了内存,省去了创建相同字符串的时间,同时提升了性能;另一方面,字符串池的缺点就是牺牲了JVM在常量池中遍历对象所需要的时间,不过其时间成本相比而言比较低。

intern方法使用一个初始为空的字符串池,它由类String独自维护。当调用 intern方法时,如果池已经包含一个等于此String对象的字符串(用equals(oject)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象的引用。 对于任意两个字符串s和t,当且仅当s.equals(t)为true时,s.instan() == t.instan才为true。所有字面值字符串和字符串赋值常量表达式都使用 intern方法进行操作。

GC回收字符串池中维护了共享的字符串对象,这些字符串不会被垃圾收集器回收。

Java语言规范(Java Language Specification)中对字符串做出了如下说明:每一个字符串常量都是指向一个字符串类实例的引用。字符串对象有一个固定值。字符串常量,或者一般的说,常量表达式中的字符串都被使用方法 String.intern进行保留来共享唯一的实例。以上是Java语言规范中的原文,比较官方,用更通俗易懂的语言翻译过来主要说明了三点:1)每一个字符串常量都指向字符串池中或者堆内存中的一个字符串实例;2)字符串对象值是固定的,一旦创建就不能再修改;3)字符串常量或者常量表达式中的字符串都被使用方法String.intern()在字符串池中保留了唯一的实例。并且给出了测试程序如下:

img

编译单元:

img

输出:

img

这个例子说明了6点:

  • 同一个包下同一个类中的字符串常量的引用指向同一个字符串对象;

  • 同一个包下不同的类中的字符串常量的引用指向同一个字符串对象;

  • 不同的包下不同的类中的字符串常量的引用仍然指向同一个字符串对象;

  • 由常量表达式计算出的字符串是在编译时进行计算,然后被当作常量;

  • 在运行时通过连接计算出的字符串是新创建的,因此是不同的;

  • 通过计算生成的字符串显示调用intern方法后产生的结果与原来存在的同样内容的字符串常量是一样的。

    从上面的例子可以看出,字符串常量在编译时计算和在运行时计算,其执行过程是不同的,得到的结果也是不同的。我们来看看下面这段代码:

    img

    代码输出如下:

    img

    为什么出现上面的结果呢?这是因为,字符串字面量拼接操作是在Java编译器编译期间就执行了,也就是说编译器编译时,直接把"java"、“language"和"specification"这三个字面量进行”+“操作得到一个"javalanguagespecification” 常量,并且直接将这个常量放入字符串池中,这样做实际上是一种优化,将3个字面量合成一个,避免了创建多余的字符串对象。而字符串引用的"+“运算是在Java运行期间执行的,即str + str2 + str3在程序执行期间才会进行计算,它会在堆内存中重新创建一个拼接后的字符串对象。总结来说就是:字面量”+“拼接是在编译期间进行的,拼接后的字符串存放在字符串池中;而字符串引用的”+"拼接运算实在运行时进行的,新创建的字符串存放在堆中。

    总结:字符串是常量,字符串池中的每个字符串对象只有唯一的一份,可以被多个引用所指向,避免了重复创建内容相同的字符串;通过字面值赋值创建的字符串对象存放在字符串池中,通过关键字new出来的字符串对象存放在堆中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555413.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用dl元素编辑html个人信息,html dl dt dd标签元素语法结构与使用

dl dt dd认识及dl dt dd使用方法一、dl dt dd认识 - TOPhtml 是一组合标签,使用了dt dd最外层就必须使用dl包裹,此组合标签我们也又叫表格标签,与table表格类似组合标签,故名我们也叫dl表格(扩展阅读:table tr td、…

千牛怎么注销卖家店铺_新店铺怎么拥有亚马逊购物车?亚马逊小卖家如何尽快获得黄金购物车?...

我做跨境电商也有六年的时间了,在电商这个行业也有自己的一些经验。经验也许没有其他大卖家丰富,但会将我知道的都进行分享。如果有不懂得亚马逊问题可以我(V:772024802)。我这里给大家安排一堂直播课,可以系统的帮你解决做亚马逊…

mysql中like是否使用索引

一.测试数据 CREATE TABLE test_orderdetail (id int(11) NOT NULL AUTO_INCREMENT,order_id int(11) DEFAULT NULL,product_name varchar(100) DEFAULT NULL,cnt int(11) DEFAULT NULL,create_date datetime DEFAULT NULL,PRIMARY KEY (id),KEY idx_orderid_productname (pro…

电子科大16秋计算机应用基础在线作业一,电子科大16秋《计算机应用基础(本科)》在线作业3...

电子科技大学电子科大16秋《计算机应用基础(本科)》在线作业3一、单选题(共35 道试题,共70 分。)1. 在Windows,打开一个菜单后,其中某菜单项会出现下属级联菜单的标识是()。A. 菜单右侧有一组英文提示B. 菜单右侧有一个黑色三角形C. 菜单左侧有一个黑色圆点D. 菜单左…

wince手机投屏代码_除了 iOS,这些手机系统你肯定没用过

今年是2020年,智能手机市场经过大浪淘沙,留存下来的品牌可以说都是精品,国外的像苹果、三星、索尼、LG,国内有华为、小米、OV、魅族....都是有特色有竞争力的。华为在海外的巨幅广告牌但是大家有没有发现,如此多的手机…

SpringBoot读取Resource下文件的几种方式

最近在项目中涉及到Excle的导入功能,通常是我们定义完模板供用户下载,用户按照模板填写完后上传;这里待下载模板位置为resource/excleTemplate/test.xlsx,尝试了四种读取方式,并且测试了四种读取方式分别的windows开发…

kido机器人用流量吗_国脉电信200元天网卡,交1700流量无线用,拉人加入还会有不错的收益,你信吗?反正我是不信!...

最近又很多人咨询小编国脉天电信网卡是真的吗,是不是骗人的。关于国脉天网骗局,反传销联合会曾在网站发表了一篇关于国脉天网骗局的文章。今天来说说200元的国脉天网和1700的流量包。首先来说说200元购买的国脉天网卡,这个也就是国脉电信推广…

孩子学计算机最佳年龄,孩子学编程最佳年龄是多少

随着IT技术几十年的发展,编程也正变得越来越简单、易用,而不再是那么复杂、繁琐。那么孩子学编程最佳年龄是多少呢?孩子学编程的最佳年龄3-5岁的儿童可以先进行少儿编程语言启蒙,正式学习编程建议在上小学后。国外脑科学实证研究表…

messageformat.format() 自定义参数名_DedeCMS的Java版mcms 第四季之一: 自定义插件

自定义mcms插件包含自定义字典、自定义搜索、自定义模型、自定义表单、自定义页面等功能依赖: Apache Maven<dependency><groupId>net.mingsoft</groupId><artifactId>ms-mdiy</artifactId><version>当前版本</version> </de…

计算机里的网络是什么意思啊,计算机网络中本地站点是什么意思

Dreamweaver 站点提供一种组织所有与 Web 站点关联的文档的方法。通过在站点中组织文件&#xff0c;可以利用 Dreamweaver 将站点上传到 Web 服务器、自动跟踪和维护链接、管理文件以及共享文件。若要充分利用 Dreamweaver 的功能&#xff0c;需要定义一个站点。Dreamweaver 站…

angularjs input标签用一个日期插件后数据不能双向绑定了_微信如何定时发朋友圈?(最方便最好用的办法!)...

微信怎么发朋友圈&#xff08;微信如何定时发朋友圈&#xff09;作为一个运营新媒体的小编&#xff0c;很多情况下&#xff0c;我都会遇到定时发文的情况&#xff0c;对于我来说&#xff0c;定时发文很简单。只要将文案编辑好&#xff0c;使用平台的定时发文功能就可以&#xf…

POI的getLastRowNum() getPhysicalNumberOfRows()区别

// 获得总记录数&#xff08;行数&#xff09;int lastRowNum sheet.getLastRowNum();int rowNumsheet.getPhysicalNumberOfRows();同样的都是获取Excel工作sheet行数的两个方法 getLastRowNum()getPhysicalNumberOfRows()他们的主要区别是&#xff1a; getPhysicalNumberOfR…

java获取当月有几天_腾讯程序员裸辞3个月,转行去送外卖,曝出当月收入网友:又骗我去送外卖...

最近在职业论坛看到这样一个热门的帖子&#xff0c;“腾讯员工裸辞3个月&#xff0c;转行去送外卖&#xff0c;曝出当月收入网友&#xff1a;又骗我去送外卖“到底怎么回事&#xff1f;请往下看。原来一位腾讯员工分享了自己从程序员到外卖员的经历&#xff0c;据男子说在腾讯&…

设置response.setContentType(“application/json;charset=utf-8“)后还是中文乱码

首先是我确认了response.setContentType(“application/json;charsetutf-8”)是设置正确了 代码如下&#xff1a; 找不到头绪&#xff0c;看了一下前端请求头信息&#xff1a; 确定是response.setContentType(“application/json;charsetutf-8”)没有生效&#xff0c;代码是没…

二年级计算机认识键盘教案,关于《认识键盘》的教学反思

关于《认识键盘》的教学反思键盘是计算机最基本、最常用的输入设备&#xff0c;通过键盘接口与主机相连&#xff0c;用户通过按键向计算机输入信息。本课学生学习的是标准的104键键盘&#xff0c;其中3个是Windows专用键。学生已经学习了鼠标操作的能力&#xff0c;在第七课安排…

Java实现文件写入——IO流(输入输出流详解)

输入输出的重要性&#xff1a; 输入和输出功能是Java对程序处理数据能力的提高&#xff0c;Java以流的形式处理数据。流是一组有序的数据序列&#xff0c;根据操作的类型&#xff0c;分为输入流和输出流。 程序从输入流读取数据&#xff0c;向输出流写入数据。Java是面向对象…

base64解密后乱码_血泪教训!记一个JavaMail 附件乱码的问题

说到乱码&#xff0c;很多人都遇到过&#xff0c;“哎呀&#xff0c;你这个编码是不是UTF-8&#xff01;”&#xff0c;“你这个会不会操作系统不一致导致的&#xff1f;”&#xff0c;“肯定是两边编码不一致”。不过我们今天说的问题&#xff0c;还真不是这个问题导致的。问题…

最新电脑版二级计算机视频怎么打开,电脑版钉钉如何打开视频会议中录制的视频...

电脑版钉钉如何打开视频会议中录制的视频腾讯视频/爱奇艺/优酷/外卖 充值4折起电脑版钉钉软件被很多人使用&#xff0c;用来学习或者工作&#xff0c;想要聚集一些人讨论问题&#xff0c;因此会开视频会议&#xff0c;那么为了能够后期看视频会议&#xff0c;因此会选择录制视频…

POI 单元格类型CellType

1. 单元格类型 单元格的内容决定了单元格的类型&#xff0c;POI中定义的7种单元格类型&#xff1a; 日期数据对应的单元格类型是CellType.NUMERIC&#xff0c;默认以浮点型数显示&#xff0c;显示为日期格式需要设置单元格样式DataFormat字符型单元格内容也可以为富文本Ric…

extjs 渲染之前的方法_Unity通用渲染管线(URP)系列(十一)——后处理(Bloom)...

200篇教程总入口&#xff0c;欢迎收藏&#xff1a;放牛的星星&#xff1a;[教程汇总持续更新]Unity从入门到入坟——收藏这一篇就够了​zhuanlan.zhihu.com本文重点内容&#xff1a;1、创建简单的post-FX栈2、修改渲染后的图像3、需要的时候完成后处理的呈现4、制作Bloom的效果…