java字符串底层实现_「JAVA」细述合理创建字符串,分析字符串的底层存储,你不该错过...

a080873ebff055fd2d819ff8f5c40983.png

Java基础之字符串操作——String

字符串

什么是字符串?如果直接按照字面意思来理解就是多个字符连接起来组合成的字符序列。为了更好的理解以上的理论,我们先来解释下字符序列,字符序列:把多个字符按照一定的顺序排列起来;而字符序列就是作为字符串的内容而存在的。所以可以把字符串理解为:把多个字符按照一定的顺序排列起来而构成的排列组合。

如果还是不好理解,没有关系,我还有法宝。我们可以用烤串来比喻说明,可以把字符串看作是烤串,烤串上的每一块肉都相当于是一个字符。把一块块肉按照肥瘦相间的顺序排列并串起来便成了我们吃的烤串,同理,把多个字符按照一定的顺序“串”起来就构成了字符串。

字符串的分类,字符串分为可变的字符串和不可变的字符串两种;这里的不可变与可变指的是字符串的对象还是不是同一个,会不会因为字符串对象内容的改变而创建新的对象。

不可变的字符串:当字符串对象创建完毕之后,该对象的内容(上述的字符序列)是不能改变的,一旦内容改变就会创建一个新的字符串对象;Java中的String类的对象就是不可变的。

可变的字符串:StringBuilder类和StringBuffer类的对象就是可变的;当对象创建完毕之后,该对象的内容发生改变时不会创建新的对象,也就是说对象的内容可以发生改变,当对象的内容发生改变时,对象保持不变,还是同一个。

String 类

String类表示不可变的字符串,当前String类对象创建完毕之后,该对象的内容(字符序列)是不变的,因为内容一旦改变就会创建一个一个新的对象。

String对象的创建:

方式一:通过字面量赋值创建,String s1 = "laofu";需要注意这里是双引号:"",区别与字符char类型的单引号:'';

方式二:通过构造器创建, String s2 = new String("laofu");;

以上两种创建方式的对象在JVM中又是如何分布的呢? 分别有什么区别呢?

方式一和方式二在JVM中又是如何分布?

58b35fd2b21f98fbe145c29f8859649e.png

上图中的常量池:用于存储常量的地方内存区域,位于方法区中。常量池又分为编译常量池和运行常量池两种:

编译常量池:当把字节码加载进JVM的时候,其中存储的是字节码的相关信息(如:当前执行到的字节码行号等)。

运行常量池:其中存储的是代码中的常量数据。

方式一和方式二有何不同?

方式一:String s1 = "laofu";有可能只创建一个String对象,也有可能创建不创建String对象;如果在常量池中已经存在"laofu",那么对象s1会直接引用,不会创建新的String对象;否则,会先在常量池先创建常量"laofu"的内存空间,然后再引用。

方式二:String s2 = new String("laofu");最多会创建两个String对象,最少创建一个String对象。可使用new关键字创建对象是会在堆空间创建内存区域,这是第一个对象;然后对象中的字符串字面量可能会创建第二个对象,而第二个对象如方式一中所描述的那样,是有可能会不被创建的,所以至少创建一个String对象。

字符串的本质,字符串在底层其实就是char[],char表示一个字符,比如:

String str = "laofu";

等价于

char[] cs = new char[]{'l','a','o','f','u'};

db9b2ef2c2f06e2ce3751f84cfd29573.png

String对象的空值:

对象引用为空,即:String s1 = null;此时s1没有初始化,也在JVM中没有分配内存空间。

对象内容为空字符串, 比如:String s2 = "";此时对象s2已经初始化,值为"",JVM已经为其分配内存空间。

字符串的比较:使用"=="和"equals"会有不同效果,详情在之前的文章中分享过:[JAVA] 只知对象属性,不知类属性?就算类答应,static都不答应

使用==号:用于比较对象引用的内存地址是否相同。

使用equals方法:在Object类中和==号相同,但在自定义类中,建议覆盖equals方法去实现比较自己内容的细节;由于String类覆盖已经覆盖了equals方法,所以其比较的是字符内容。

d4618b6aa29281c24ad62e59d2d15f60.png

所以可以这样来判断字符串非空:

对象引用不能为空:s1 != null;;

字符内容不能为空字符串(""):"".equals(s1);;

如果上述两个条件都满足,说明字符串确实为空!

字符串拼接:Java中的字符串可以通过是"+"实现拼接,那么代码中字符串拼接在JVM中又是如何处理的呢?我们通过一个例子说明:通过比较拼接字符串代码编译前后的代码来查看JVM对字符串拼接的处理。

06d05b2111cb2e9b2ba092c4d50f60a2.png

通过上述例子不难发现,JVM会对字符串拼接做一些优化操作,如果字符串字面量之间的拼接,无论有多少个字符串,JVM都会一样的处理;如果是对象之间拼接,或者是对象和字面量之间的拼接,亦或是方法执行结果参与拼接,String内部会使用StringBuilder先来获取对象的值,然后使用append方法来执行拼接。由此可以总结得出:

使用字符串字面量创建的字符串,也就是单独使用""引号创建的字符串都是直接量,在编译期就会将其存储到常量池中;

使用new String("")创建的对象会存储到堆内存中,在运行期才创建;

使用只包含直接量的字符串连接符如"aa" + "bb"创建的也是直接量,这样的字符串在编译期就能确定,所以也会存储到常量池中;

使用包含String直接量的字符串表达式(如"aa" + s1)创建的对象是运行期才创建的,对象存储在堆中,因为其底层是创新了StringBuilder对象来实现拼接的;

5. 无论是使用变量,还是调用方法来连接字符串,都只能在运行期才能确定变量的值和方法的返回值,不存在编译优化操作。

String 的常用API

这里列举了一些常用String API,更多的可以查阅jdk使用手册,做Java一定得学会查阅jdk手册。

f7db5b5bb963d55ca8567b384044b470.png

String 的创建和转换:

byte[] getBytes():把字符串转换为byte数组。

char[] toCharArray():把字符串转换为char数组。

String(byte[] bytes):把byte数组转换为字符串。

String(char[] value):把char数组转换为字符串。

获取字符串信息

int length() :返回此字符串的长度。

char charAt(int index) :返回指定索引处的 char值。

int indexOf(String str) :返回指定字符串在此字符串中首次(从最左边算起)出现处的索引。

int lastIndexOf(String str) :返回指定字符串在此字符串中最后(最右边算起)出现处的索引。

字符串比较判断

boolean equals(Object anObject): 将此字符串与指定的对象比较。

boolean equalsIgnoreCase(String anotherString): 将此 String 与另一个 String 做忽略大小写的比较。

boolean contentEquals(CharSequence cs): 将此字符串与指定的 CharSequence 比较,比较的是内容;

ps:String类是现实了CharSequence(字符序列)接口的。

字符串大小写转换:调用方法的字符串就是当前字符串

String toUpperCase(): 把当前字符串转换为大写

String toLowerCase(): 把当前字符串转换为小写

StringBuilder/StringBuffer

先来分别使用String/StringBuilder/StringBuffer来拼接30000次字符串,对比各自损耗的时间,经过测试发现:

String做字符串拼接的时候,耗时最高,性能极低,原因是String内容是不可变的,每次内容改变都会在内存中创建新的对象。

性能最好的是StringBuilder,其次是StringBuffer,最后是String。StringBuilder和StringBuffer区别并不是很大,也有可能是测试次数还不够吧。感兴趣的小伙伴可以增加拼接次数来看看。代码很简单,就不展示出来了。

所以在开发中拼接字符串时,优先使用StringBuffer/StringBuilder,不到万不得已,不要轻易使用String。

StringBuilder以及StringBuffer的区别

StringBuffer和StringBuilder都表示可变的字符串,两种’的功能方法都是相同的。但唯一的区别:

StringBuffer:StringBuffer中的方法都使用了synchronized修饰符,表示同步操作,在多线程并发的时候可以保证线程安全,但在保证线程安全的时候,对其性能有一定影响,会降低其性能。

StringBuilder:StringBuilder中的方法都没有使用了synchronized修饰符,线程不安全,正因为如此,其性能较高。

对并发安全没有很高要求的情况下,建议使用StringBuilder,因为其性能很高。像这样的情况会较多些。使用StringBuilder无参数的构造器,在底层创建了一个长度为16的char数组:

cd2fc50dd07d43d66cd524f5e0f8d4c1.png

此时该数组只能存储16个字符,如果超过了16个字符,会自动扩容(创建长度更大的数组,再把之前的数组拷贝到新数组),此时性能极低;如果事先知道大概需要存储多少字符,可以通过构造器来设置字符的初始值:

7d7ffc6de2b243a0d042078ea81f54d1.png

//创建一个长度为80的char数组.

new StringBuilder(80);

StringBuilder的常用方法:

append(Object val):追加任意类型数据到当前StringBuilder对象中。

StringBuilder deleteCharAt(int index) :删除字符串中指定位置的字符。

完结。虽然老夫不正经,但老夫一身的才华

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

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

相关文章

查看oracle会话和进程_带有Oracle Digital Assistant和Fn Project的会话式UI。 第三部分,迁移到云...

查看oracle会话和进程在这篇文章中,我将继续在Oracle Digital Assistant和Oracle Digital Assistant之上为FlexDeploy实现对话式UI的故事。 Fn项目 。 今天,我将围绕聊天机器人工作的无服务器API迁移到云中,因此整个解决方案都在云中工作&am…

浏览器用户脚本管理器(Tampermonkey)

文章目录脚本管理器的好处是什么?用户脚本管理器有哪些?如何使用?安装脚本示例常用脚本脚本管理器的好处是什么? 用户脚本管理器将在您的用户脚本管理方面提供更多的便利。 它提供了诸如便捷脚本安装、自动更新检查、标签中的脚本…

服务器$java_top路径_ERP实施项目-MD120_FIN000_即时打印_V1.0

中国移动项目即时打印开发在此将web的即时打印开发成通用程序。1、首先通过创建rtf模板制定报表的输出格式;2、将需要输出的数据插入客户化表cux_fnd_xml_pool中;3、通过EBS功能调用CuxFndXmlpViewer.jsp。此jsp程序会根据传入的参数判断调用哪个rtf模板…

通讯网关 api网关_API网关正在经历身份危机

通讯网关 api网关这些年来,API网关正在经历一些身份危机 。 它们是否是集中的共享资源,从而促进了API对外部实体的公开和治理? 它们是集群入口哨兵,可以严格控制哪些用户流量进入或离开集群吗? 还是他们根据自己拥有…

百度搜索引擎使用技巧

1.在指定的网站搜索内容 在搜索框输入:site:youku.com 蛋炒饭,则只会返回优酷网站上关于蛋炒饭的内容 2.屏蔽指定的网站 例如,搜索“内存溢出”,但是不希望看到 csdn 网站相关的内容,你可以在搜索框输入:内…

docker 容器监控_以简便的方式监控Docker容器中的ADF应用程序

docker 容器监控在这篇简短的文章中,我将展示一种简单的方法来确保在Docker容器中运行的ADF应用程序在内存利用率方面是健康的Java应用程序。 我将使用标准工具JConsole,它是计算机上JDK安装的一部分。 如果存在问题(例如,内存泄漏…

phpexcel 日期 时分秒_thinkPHP+PHPExcel实现读取文件日期的方法含时分秒

Vendor(PHPExcel.PHPExcel.IOFactory);$inputFileName Public/demo/demo.xls;$objReader new PHPExcel_Reader_Excel5();$objPHPExcel $objReader->load($inputFileName);$sheet $objPHPExcel->getSheet(0);$highestRow $sheet->getHighestRow(); // 取得总行数$…

css中的display属性值:table,table-row,table-cell

table&#xff1a;此元素会作为块级表格来显示&#xff08;类似 <table>&#xff09;&#xff0c;表格前后带有换行符。 table-row&#xff1a;此元素会作为一个表格行显示&#xff08;类似 <tr>&#xff09;。 table-cell&#xff1a;此元素会作为一个表格单元格显…

Bootstrap的学习

文章目录概念入门响应式布局响应式布局的实现&#xff08;栅格系统&#xff09;示例代码注意事项栅格系统参考视频应用 Bootstrap 的组件概念 一个前端开发的框架&#xff0c;Bootstrap&#xff0c;来自Twitter&#xff0c; 是目前很受欢迎的前端框架。Bootstrap 是基于HTML、…

jdk8 string::_JDK 12的String :: transform方法的简要但复杂的历史

jdk8 string::最近有人提议从JDK 12中删除Java预览功能Raw String Literals &#xff08; JEP 326 &#xff09;&#xff0c; 现在正式宣布将删除该预览功能 &#xff08; Java SE 12 [JSR 386] 25版将其删除 &#xff09;。 JDK String类中已添加了几种方法来支持此功能。 即使…

注册界面的实现案例视频(前端开发)

视频1&#xff1a;https://live.csdn.net/v/182184 视频2&#xff1a;https://live.csdn.net/v/182185 视频3&#xff1a;https://live.csdn.net/v/182186 视频4&#xff1a;https://live.csdn.net/v/182200

jdbc如何写csv文件_Java:将JDBC结果集作为CSV流化

jdbc如何写csv文件在上一篇文章中 &#xff0c;我展示了如何将java.sql.ResultSet转换为JSON并将其流回调用方。 这篇文章是关于以CSV格式流式传输。 流式传输使您可以一点一点地传输数据&#xff0c;而不必将所有数据都加载到服务器的内存中。 例如&#xff0c;考虑以下Resul…

使用Bootstrap开发网站首页

视频1&#xff1a;https://live.csdn.net/v/182207 视频2&#xff1a;https://live.csdn.net/v/182208 视频3&#xff1a;https://live.csdn.net/v/182209

在java中3.14156d表示_2006年9月计算机等级考试二级Java笔试真题

一、选择题(每小题2分&#xff0c;共70分)下列各题A)、B)、C)、D)四个选项中&#xff0c;只有一个选项是正确的&#xff0c;请将正确选项涂写在答题卡相应位置上&#xff0c;答在试卷上不得分。(1)下列选项中不符合良好程序设计风格的是_____。A)源程序要文档化B)数据说明的次序…

apigee 安装_APIGEE:用于API代理的CI / CD管道

apigee 安装在本文中&#xff0c;我们将看到如何为APIGEE API代理创建CI / CD管道。 我已经参考了APIGEE社区上同一主题的几篇文章。 这些给了一些关于如何为API代理设置CI / CD管道的想法。 这是我用来设置CI / CD的工具。 詹金斯 节点 蜂胶 新人 APIGEE管理API 确保已创…

超链接标签/<a>标签

保留 <a> 标签的点击功能&#xff0c;但是点击不需要跳转&#xff0c;也就是取消 href 属性的功能&#xff0c;可以这样做&#xff1a; <a href"javascript:void(0);">test2</a>href 属性不能去掉&#xff0c;否则看不到链接样式。

php model层怎么写逻辑,目前用php框架的话,大家会把逻辑写到model中吗?

目前用php框架的话&#xff0c;大家会把逻辑写到model中吗&#xff1f;还是model只做数据的添加删除 修改操作&#xff1f;如果说是简单 mvc框架 你们把逻辑写在哪里&#xff1f;controller&#xff1f;还是说自己弄了个逻辑层&#xff1f;回复内容&#xff1a;目前用php框架的…

gradle项目 构建_使用Gradle构建Monorepo项目

gradle项目 构建根据Wikipedia的说法 &#xff0c; monorepo是一种软件开发策略&#xff0c;其中许多项目存储在同一资源库中。 这种策略可以快速检测到因依赖关系的更改而导致的潜在问题和破坏&#xff0c;并且已被许多使用大型代码库的组织采用&#xff0c;例如Google&#x…

jsoup爬虫教程技巧_Jsoup V的幕后秘密:优化的技巧和窍门

jsoup爬虫教程技巧我们已经把事情做好了&#xff0c;现在是时候加快工作速度了。 我们会牢记Donald Knuth的警告&#xff1a;“大约97&#xff05;的时间我们应该忘记效率低下&#xff1a;过早的优化是万恶之源”。 根据Jonathan Hedley的介绍&#xff0c;他使用YourKit Java …

DOM(document object model),文档对象模型

DOM 将标记语言文档一次性加载进内存中&#xff0c;在内存中形成一棵 DOM 数。