【面试精讲】String是如何实现的?String源码分析

【面试精讲】String是如何实现的?String源码分析

目录

一、String实现机制

二、String不可变性(使用final修饰)

三、String 和 StringBuilder、StringBuffer 的区别

四、==和equals的区别

五、String创建对象与JVM辨析

六、String源码解析

1、compareTo()

2、 equals() 

总结

 博主v:XiaoMing_Java


在Java中,String类是使用最频繁的类之一。由于其不可变性、效率以及如何影响内存使用等方面的特点,String类成为了Java编程语言的一个核心组成部分。本文深入探讨String的实现机制、它的源码结构、特点以及用final修饰的好处。

一、String实现机制

在Java中,String被设计为不可变(immutable)的对象。这意味着一旦String对象被创建,它所包含的字符序列就不能被修改。每次对字符串进行操作时(例如拼接、替换字符等),实际上都会创建一个新的String对象。

从JDK 1.0到JDK 8,String内部是通过一个char数组来实现的,保存着所有的字符数据。从JDK 9开始,String类的内部实现改为使用byte数组加上一个编码标记(coder),以更有效地处理不同的字符集,优化内存使用和性能。

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {// 用于存储字符串的值private final char value[];// 缓存字符串的 hash codeprivate int hash; // Default to 0
}

自JDK 9起,为了提升空间效率和性能,String的内部表示发生了变化,使用byte数组加上一个编码标志字段coder来存储字符串,如下所示:

// JDK 9及以后的String内部结构
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {// 实际存储字符串内容的byte数组private final byte[] value;// 字符串使用的编码标识(用于区分使用Latin-1还是UTF-16编码)private final byte coder;// 缓存字符串的哈希码private int hash; // 默认为0// 构造方法之一,用于从字符数组初始化字符串public String(char[] value) {// 这里简化了实际的实现细节this.value = StringLatin1.toBytes(value);this.coder = LATIN1;}// length() 方法实现public int length() {return value.length >> coder;}
}

二、String不可变性(使用final修饰)

String对象一旦被创建,其内容就不能被改变。任何对String的修改操作都会导致新的String对象的生成。这个特性带来了以下好处:

安全性:String常作为参数传递,其不可变性保证了数据不会被意外改变。防止子类改变父类(String)的行为,确保所有String实例都具有String定义的行为。

线程安全:在多线程环境下,String可以被自由共享而无需同步控制。

高效:因为String的内容不变,所以其哈希码可以被缓存,提高哈希表操作的效率。性能优化:

简化设计:由于不需要考虑子类的影响,使得String类的设计更简单、更稳定

 

三、String 和 StringBuilder、StringBuffer 的区别

String类重载了+运算符,使得字符串连接操作非常方便。然而,频繁的字符串连接操作会产生大量临时字符串对象,影响性能。为了解决这个问题,Java引入了StringBuilderStringBuffer两个类,它们允许在单个字符序列上执行可变操作。

因为 String 类型是不可变的,所以在字符串拼接的时候如果使用 String 的话性能会很低,因此我们就需要使用另一个数据类型 StringBuffer,它提供了 append 和 insert 方法可用于字符串的拼接,它使用 synchronized 来保证线程安全。

在 JDK 1.5 有了 StringBuilder,它同样提供了 append 和 insert 的拼接方法,在非并发操作的环境下可使用 StringBuilder 来进行字符串拼接。

四、==和equals的区别

== 对于基本数据类型来说,是用于比较 “值”是否相等的;而对于引用类型来说,是用于比较引用地址是否相同的。

// Object 中的 equals() 方法其实就是 ==
public boolean equals(Object obj) {return (this == obj);
}// 而String重写equals()方法把它修改成比较两个字符串的值是否相等
public boolean equals(Object anObject) {// 对象引用相同直接返回 trueif (this == anObject) {return true;}// 判断需要对比的值是否为 String 类型,如果不是则直接返回 falseif (anObject instanceof String) {String anotherString = (String)anObject;int n = value.length;if (n == anotherString.value.length) {// 把两个字符串都转换为 char 数组对比char v1[] = value;char v2[] = anotherString.value;int i = 0;// 循环比对两个字符串的每一个字符while (n-- != 0) {// 如果其中有一个字符不相等就 true false,否则继续对比if (v1[i] != v2[i])return false;i++;}return true;}}return false;
}

五、String创建对象与JVM辨析

String 常见的创建方式有两种,new String() 的方式和直接赋值的方式

直接赋值的方式会先去字符串常量池中查找是否已经有此值,如果有则把引用地址直接指向此值,否则会先在常量池中创建,然后再把引用指向此值;

new String() 的方式一定会先在堆上创建一个字符串对象,然后再去常量池中查询此字符串的值是否已经存在,如果不存在会先在常量池中创建此字符串,然后把引用的值指向此字符串

JDK 1.7 之后把永生代换成的元空间,把字符串常量池从方法区移到了 Java 堆上。

六、String源码解析

1、compareTo()

public int compareTo(String anotherString) {int len1 = value.length;int len2 = anotherString.value.length;// 获取到两个字符串长度最短的那个 int 值int lim = Math.min(len1, len2);char v1[] = value;char v2[] = anotherString.value;int k = 0;// 对比每一个字符while (k < lim) {char c1 = v1[k];char c2 = v2[k];if (c1 != c2) {// 有字符不相等就返回差值return c1 - c2;}k++;}return len1 - len2;
}

2、 equals() 

public boolean equals(Object anObject) {// 对象引用相同直接返回 trueif (this == anObject) {return true;}// 判断需要对比的值是否为 String 类型,如果不是则直接返回 falseif (anObject instanceof String) {String anotherString = (String)anObject;int n = value.length;if (n == anotherString.value.length) {// 把两个字符串都转换为 char 数组对比char v1[] = value;char v2[] = anotherString.value;int i = 0;// 循环比对两个字符串的每一个字符while (n-- != 0) {// 如果其中有一个字符不相等就 true false,否则继续对比if (v1[i] != v2[i])return false;i++;}return true;}}return false;
}

总结

String在Java中的地位极其重要,其设计精巧、使用广泛。通过不可变性设计,String提供了高度的安全性和线程安全,同时final修饰符进一步确保了其不变契约的稳定性。了解String的内部实现和特点对于写出高效、安全和易维护的Java代码至关重要。

Java开发者应当熟练掌握String的使用,并在合适的场景选择使用StringBuilderStringBuffer以优化性能。此外,深入理解String的设计哲学也有助于开发者设计自己的不可变类,为构建稳定和高效的Java应用打下坚实的基础。

如果本文对你有帮助 欢迎 关注 、点赞 、收藏 、评论, 博主才有动力持续记录遇到的问题!!!

 博主v:XiaoMing_Java

  📫作者简介:嗨,大家好,我是 小明(小明Java问道之路),互联网大厂后端研发专家,2022博客之星TOP3 / 博客专家 / CSDN后端内容合伙人、InfoQ(极客时间)签约作者、阿里云签约博主、全网 6 万粉丝博主。


🍅 文末获取联系 🍅  👇🏻 精彩专栏推荐订阅收藏 👇🏻

专栏系列(点击解锁)

学习路线(点击解锁)

知识定位

🔥Redis从入门到精通与实战🔥

Redis从入门到精通与实战

围绕原理源码讲解Redis面试知识点与实战

🔥MySQL从入门到精通🔥

MySQL从入门到精通

全面讲解MySQL知识与企业级MySQL实战

🔥计算机底层原理🔥

深入理解计算机系统CSAPP

以深入理解计算机系统为基石,构件计算机体系和计算机思维

Linux内核源码解析

围绕Linux内核讲解计算机底层原理与并发

🔥数据结构与企业题库精讲🔥

数据结构与企业题库精讲

结合工作经验深入浅出,适合各层次,笔试面试算法题精讲

🔥互联网架构分析与实战🔥

企业系统架构分析实践与落地

行业最前沿视角,专注于技术架构升级路线、架构实践

互联网企业防资损实践

互联网金融公司的防资损方法论、代码与实践

🔥Java全栈白宝书🔥

精通Java8与函数式编程

本专栏以实战为基础,逐步深入Java8以及未来的编程模式

深入理解JVM

详细介绍内存区域、字节码、方法底层,类加载和GC等知识

深入理解高并发编程

深入Liunx内核、汇编、C++全方位理解并发编程

Spring源码分析

Spring核心七IOC/AOP等源码分析

MyBatis源码分析

MyBatis核心源码分析

Java核心技术

只讲Java核心技术

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

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

相关文章

Spring Web MVC入门(1)

什么是Spring Web MVC? 定义:Spring Web MVC是基于Servlet构建的原始Web框架,从一开始就包含在Spring框架中.它的正式名称"Spring Web MVC"来自其源模块的名称(Spring-webmvc),但是它通常被称为"Spring MVC". 什么是Servlet? Servlet是一种实现动态页面…

springboot+ssm基于vue.js的客户关系Crm管理系统

系统包含两种角色&#xff1a;管理员、用户&#xff0c;主要功能如下。 ide工具&#xff1a;IDEA 或者eclipse 编程语言: java 数据库: mysql5.7 框架&#xff1a;ssmspringboot都有 前端&#xff1a;vue.jsElementUI 详细技术&#xff1a;springbootSSMvueMYSQLMAVEN 数据库…

电梯机房秀

每天乘坐电梯&#xff0c;您见过电梯的机房吗&#xff1f;来&#xff0c;跟着小伍去看看吧。Lets go&#xff01; 电梯还能节能呢&#xff0c;您知道么&#xff1f;正好&#xff0c;小伍一块带您看看电梯节能装置(●◡●) 目前电梯节能装置已广泛应用于三菱、富士、日立、奥的斯…

案例分析篇12:可靠性设计考点(2024年软考高级系统架构设计师冲刺知识点总结系列文章)

专栏系列文章推荐: 2024高级系统架构设计师备考资料(高频考点&真题&经验)https://blog.csdn.net/seeker1994/category_12593400.html 【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】(2024年软考高级系统架构设计师冲刺知识点总结-案例分析篇-…

深入理解 CSS——CSS进阶与实践(5w字高频面试题整理)

本文总结了CSS高频面试题&#xff0c;并搭配了演示动画进行CSS样式演示。介绍了关于如何理解盒模型&#xff0c;如何实现块级元素水平居中&#xff0c;如何实现两侧固定中间自适应的三栏布局、如何实现两栏布局&#xff0c;如何进行响应式设计&#xff0c;对BFC的理解&#xff…

Github上哪些好用的安全工具1

专注于web漏洞挖掘、内网渗透、免杀和代码审计&#xff0c;感谢各位师傅的关注&#xff01;网安之路漫长&#xff0c;与君共勉&#xff01; URLFinder 一款快速提取网页信息的工具。该项目可以快速爬取网页上的 URL 地址、JS 文件里的 API 接口等信息&#xff0c;支持批量抓取…

市场复盘总结 20240314

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 一支股票 10%的时候可以操作&#xff0c; 90%的时间适合空仓等待 二进三&#xff1a; 进级率中 25% 最常用的…

【CSP试题回顾】201703-2-学生排队

CSP-201703-2-学生排队 解题思路 初始化队列&#xff1a;通过输入获得学生的数量 n&#xff0c;然后创建一个队列 queue&#xff0c;初始时这个队列中的学生按照学号从小到大的顺序排列。这是通过循环赋值实现的&#xff0c;其中每个学生的学号是其在列表中的位置加1。 处理调…

男人圣经 7

男人圣经 7 高逼格长期目标的行动飞轮1. 品牌价值和声誉2. 人脉网络和关系3. 企业文化和价值观4. 专有技术和知识产权5. 管理经验和专业知识 为什么只追求高经济、高科技&#xff1f;为什么说道德仁义是表面&#xff0c;而利益才是一切背后的真相&#xff1f; 高逼格长期目标的…

SinoDB数据库资源分析

SinoDB数据库资源主要从数据库虚处理器繁忙状况、数据库虚拟内存段、锁资源使用情况、数据空间使用率、网络连接情况等5个方面来进行分析。分别如下&#xff1a; 一、数据库虚处理器 检查项目 数据库虚处理器繁忙状况 检查命令 onstat -g rea onstat -g glo 说明 1、使用ons…

中科数安|公司办公终端、电脑文件数据 \ 资料防泄密系统

#中科数安# 中科数安是一家专注于信息安全技术与产品研发的高新技术企业&#xff0c;其提供的公司办公终端、电脑文件数据及资料防泄密系统&#xff08;也称为终端数据防泄漏系统或简称DLP系统&#xff09;主要服务于企业对内部敏感信息的安全管理需求。 www.weaem.com 该系统…

01、JS实现:去除数组中重复项的算法之一

数组去除重复项的算法&#xff1a; Ⅰ、删除排序数组中的重复项(注意&#xff1a;是已经排好序的)&#xff1a;1、题目描述&#xff1a;2、解题思路&#xff1a;3、实现代码&#xff1a; Ⅳ、小结&#xff1a; Ⅰ、删除排序数组中的重复项(注意&#xff1a;是已经排好序的)&…

ConcurrentHashMap 为什么不能插入 null?

1、典型回答 简单来说&#xff0c;ConcurrentHashMap 不允许插入 null 值是JDK 源码规定的&#xff0c;如下源码所示(此源码基于JDK 1.8)&#xff1a; 从上述源码可以看出&#xff0c;在添加方法的第一句就加了判断&#xff1a;如果 key 值为 null 或者是 value 值为 null&…

齐聚“向上的力量”,维谛技术(Vertiv)2024年合作伙伴大会成功举办

3月13日&#xff0c;维谛技术&#xff08;Vertiv&#xff0c;NYSE&#xff1a;VRT&#xff09;2024年合作伙伴大会在广东佛山顺利召开&#xff0c;本次大会以“向上的力量”为主题&#xff0c;维谛技术与数百家优秀合作伙伴&#xff08;含港台&#xff09;欢聚一堂&#xff0c;…

vue/uniapp路由history模式下宝塔空间链接打开新窗口显示404解决方法

vue/uniapp路由history模式下宝塔空间链接打开新窗口显示404&#xff0c;或者域名后带路径参数刷新就报404 解决方法&#xff1a; 宝塔中站点配置修改&#xff1a;【配置文件】中添加下面代码&#xff0c;具体如图&#xff1a; location / {try_files $uri $uri/ /index.html…

Editor.md-编辑器

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

mac安全干净卸载Anaconda3

使用which python显示当前使用的是/Users/username/anaconda3/bin/python 现在想卸载Anaconda&#xff0c;恢复使用mac系统自带的Python 删除隐藏文件目录 rm -rf ~/.anaconda修改~/.bash_profile文件&#xff0c;将anaconda相关删除 也有可能不是~/.bash_profile而是~/.zs…

三维铁木辛柯梁Matlab有限元编程 | 弹簧支座 | 弹性支撑单元| Matlab源码 | 理论文本

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

【C++】stack、queue模拟实现+仿函数

stack、queue模拟实现仿函数 stack定义stack模拟实现 queue定义queue模拟实现 priority_queue定义priority_queue模拟实现 deque定义底层分析 容器适配器定义种类 仿函数控制类里面数据的比较逻辑回调函数仿函数两者区别 铁汁们&#xff0c;今天给大家分享一篇stack、queue模拟…

移动端使用 echarts中 滚动条 dataZoom 改造为内容区域可以左右滚动

移动端使用 echarts中 滚动条 dataZoom 改造为内容区域可以左右滚动 直接上图 &#xff1a; 主要是下面这段代码&#xff1a; "dataZoom": [{"type": "inside","show": false,"xAxisIndex": [0],"zoomOnMouseWheel&…