JAVASE进阶:String常量池内存原理分析、字符串输入源码分析

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
🌌上期文章:JAVASE进阶:内存原理剖析(1)——数组、方法、对象、this关键字的内存原理
📚订阅专栏:JAVASE进阶
希望文章对你们有所帮助

String类型的变量是我们非常常用的,它是属于java.lang包下的,属于java核心包下的,直接可以使用。
这一部分的内容也是会出一点面经的,所以我需要重新梳理一下。
同时给了一个可能比较少见的问题,也就是用户输入的字符串,其底层是怎么执行的?这部分内容我会跟踪源码来做解析。

引入

先看下面语句:

String name = "哈哈哈";
name = "哈哈";

这里虽然只用了一次String语句进行声明,但是实际上还是创建了2个字符串,都创建在了字符串常量池中。因此第一句只是将字符串常量池中的"哈哈哈"的地址赋值给了左边的name,第二句是将常量池中的"哈哈"的地址赋值给了左边的name。这其中,并不存在"哈哈哈"字符串变为"哈哈"字符串的说法,即——字符串一旦创建成功,无法进行修改

字符串常量池

实际上,上述的创建方式一直都是最常用的创建方式,而且也是最推荐的方式,在这里进行一下比较。

创建String对象的两种方式:
1、直接赋值

String name = “哈哈哈”;

2、new关键字

构造方法说明
public String()创建空白字符串
public String(String s)根据传入的字符串创建字符串对象(很少用)
public String(char[] chs)根据字符数组,创建字符串对象
public String(byte[] chs)根据字节数组,创建字符串对象

字符串常量池(串池,StringTable)在之前一直都是在方法区(元空间)中的,而在jdk7开始,从方法区挪到了堆内存,但是底层的实现方式还是不变的。

查看下面语句:

String s1 = "abc";
String s2 = "abc";

第一条语句先从常量池中查看是否有这条字符串,没有就创建一个,并把地址赋值给s1,第二条语句在常量池中查找到这条字符串,直接返回地址给s2(复用),也就是说s1和s2指向了常量池中的同一条字符串了。

再看下面语句:

char[] chs = {'a', 'b', 'c'};
String s1 = new String(chs);
String s2 = new String(chs);

因为有new关键字,所以创建的过程全部在堆内存(不包括常量池)进行的,这时候会创建出两条字符串,并且s1和s2的地址是不一样的,即不会复用,显然更耗费空间。

所以,字符串常量池不仅代码简单,还因为复用机制更省内存。

字符串比较底层机理

分别分析下面语句的运行结果:

String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);

true

String s1 = "aaa";
String s2 = "bbb";
System.out.println(s1 == s2);

false

String s1 = new String("abc");
String s2 = "abc";
System.out.println(s1 == s2);

false

在第三个例子中,值一样的字符串,比较结果却是false,所以需要搞明白==到底比较的是啥。

实际上,如果是基本数据类型,直接比较的就是真实值,而字符串由于涉及到了常量池和堆内存,显然是引用数据类型,而引用数据类型比较的是地址值,由于new出来的是在堆空间的,直接赋值的方式是在字符串常量池的,因此它们根本不可能是同一个地址,因此返回false。

因此,==的方式并不适合用来比较字符串,实际比较最好使用字符串比较函数:

boolean equals()
boolean equalsIgnoreCase(): 忽略大小写比较,比如验证码

字符串输入源码分析

真实场景下,字符串可能不是直接赋值的,而是要用户自己去输入的,那么用户自己输入的字符串到底是放在常量池中的还是放在堆内存中的呢?可以验证并跟踪源码分析。

查看下列语句:

Scanner sc = new Scanner(System.in);
String s1 = sc.next();
String s2 = "abc";
System.out.println(s1 == s2);

用户输入abc,但最终输出的是false,可以猜想到,用户输入字符串后,其创建是在堆空间中进行的,进行源码分析:

1、Ctrl+鼠标进入next方法查看一下,其返回的内容是一个token,token的来源是getCompleteTokenInBuffer方法:
在这里插入图片描述
2、跟踪getCompleteTokenInBuffer方法,可以看到源码非常长:
在这里插入图片描述
但是其实只要看关键的信息,也就是return的真实信息,那些return null的其实肯定不是我们重点关注的,因此定位到正确位置:
在这里插入图片描述
3、ctrl+左键跟踪进入group:
在这里插入图片描述
4、继续跟踪group(0):
在这里插入图片描述
5、再跟踪:
在这里插入图片描述
6、继续跟踪,发现没有返回值了,就是一个定义好的接口:
在这里插入图片描述
这其实就是java设计模式的原则了,用父类去替代子类,说明这个接口的实现类还是很多的,因此没办法从这里进行分析,回到上一层的subSequence。

7、右键点击subSequence方法,并点击go to,选择Implementation,即可找到其中的所有实现类:
在这里插入图片描述
8、显然我们需要寻找有关于String的,所以点击String进入:
在这里插入图片描述
在这里插入图片描述
9、跟踪进入:
在这里插入图片描述
其实看到这个return里面带着的new的字样大致就能猜到它底层肯定是用到了new关键字了。

10、跟踪newString方法跟踪,看到了底层的new关键字:
在这里插入图片描述
这就说明了,用户用键盘输入的字符串,即sc.next(),其底层是会用到new关键字,也就是说其创建在堆空间中,所以例子中的程序返回false。

跟踪源码心得

我不是第一次跟踪源码了,每次跟踪源码都会有一些不一样的心得,在这里讲一下我目前拥有的经验:

1、无所谓跟踪进去的方法有多么复杂,先查找return真实值的那部分,其是由哪个函数创建出来的,就跟踪那个函数
2、如果return真实值的情况有多种,可以快速筛查我们到底应该跟踪哪一个:
(1)看其中的英文注释
(2)看返回值和你的需求对不对得上
(3)看函数名称,自己翻译了猜一下
3、如果跟踪到没办法再跟踪的接口,说明是父类替代的子类,返回并右键查找正确的实现类(根据需求)

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

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

相关文章

【JDBC-Mysql】使用 JDBC 操作 Mysql 数据库

【JDBC-Mysql】使用 JDBC 操作 Mysql 数据库 1&#xff09;导入依赖2&#xff09;定义Connection连接类3&#xff09;使用JDBC进行Mysql数据库操作3.1.写入3.2.删除3.3.修改3.4.查询 1&#xff09;导入依赖 <dependency><groupId>mysql</groupId><artifa…

SpringBoot使用poi将word转换为PDF并且展示

1.前言 由于最近做了一个需求&#xff0c;界面上有一个按钮&#xff0c;点击按钮后将一个文件夹中的word文档显示在页面中&#xff0c;并且有一个下拉框可以选择不同的文档&#xff0c;选择文档可以显示该文档。这里我选择使用fr.opensagres.poi.xwpf.converter.pdf-gae依赖包…

CoroNa Green acetoxymethyl (AM) ester,具有良好的细胞膜穿透能力

CoroNa Green, AM, Cell Permeant&#xff0c;CoroNa Green acetoxymethyl (AM) ester&#xff0c;CoroNa Green, AM&#xff0c;Sodium indicator 钠离子指示剂&#xff08;荧光探针&#xff09;&#xff0c;具有良好的细胞膜穿透能力&#xff0c;能够检测到细胞内钠离子的微小…

带大家详细了解msvcr120.dll丢失的原因,msvcr120.dll丢失怎样修复的方法

在使用电脑和运行应用程序时&#xff0c;我们经常会遇到与动态链接库&#xff08;Dynamic Link Library, DLL&#xff09;文件相关的错误。其中之一是 "msvcr120.dll 丢失" 的错误提示。今天我们就来详细的了解一下msvcr120.dll这个文件和分享msvcr120.dll丢失怎样修…

【目标检测】对DETR的简单理解

【目标检测】对DETR的简单理解 文章目录 【目标检测】对DETR的简单理解1. Abs2. Intro3. Method3.1 模型结构3.2 Loss 4. Exp5. Discussion5.1 二分匹配5.2 注意力机制5.3 方法存在的问题 6. Conclusion参考 1. Abs 两句话概括&#xff1a; 第一个真正意义上的端到端检测器最…

stm32--simulink开发之--timer的学习,硬件输入中断,触发事件,STM32通用定时器之输出比较模式与PWM模式(重要理解)

下面三个模块&#xff0c;一个比一个高级&#xff0c;当然使用是越来越简单 STM32F4xx系列控制器有2个高级控制定时器、10个通用定时器和2个基本定时器(推荐学习) 1&#xff0c;第一个模块&#xff1a;Timer Starts timer counter and provides current counter value Timer …

vivado 与系统设计师接口

与系统设计师接口 作为迭代I/O和时钟规划过程的一部分&#xff0c;您可以交换有关AMD设备通过导出CSV文件和IBIS模型&#xff0c;与PCB或系统设计者进行引脚连接。根据PCB或设计规范的变化&#xff0c;您可能需要将引脚重新导入为如定义和配置I/O端口中所述。完成I/O和时钟中的…

uniapp H5 px转换rpx

uniapp H5 px转换rpx 安装 px2rpx 重启 HBuilderX在要转换的文件 点击右键 点击 开启px2rpx(1px转成2rpx) 开启成功&#xff01;使用 编辑页面后 按下键盘 Ctrl s 保存&#xff01;转化成功&#xff01;当然 你也需要对使用的插件 进行转换&#xff01;否则可能导致样式出现…

51单片机温湿度数据管理系统

51单片机温湿度数据管理系统 1.硬件准备 开发板&#xff1a;51单片机 显示&#xff1a;lcd1602 温湿度模块&#xff1a;DHT11 通信模块&#xff1a;HC-08蓝牙 2.代码实现 uart.c #include "reg52.h" #include "config.h" #include <string.h>sf…

排序之计数排序

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

简述MinewSemi的GNSS模块引领体育与健康科技革新

体育与健康科技领域的创新一直在推动人们更健康、更活跃的生活方式。创新微公司的GNSS模块正成为这一变革的关键推动力。本文将深入研究MinewSemi的GNSS模块在体育和健康追踪领域的创新应用&#xff0c;探讨其如何帮助个体更全面地了解和改善自己的身体状态。 1. 个性化运动轨迹…

爬什么值得买的榜单——爬虫练习题目一(问)

爬虫题目你敢试试吗&#xff1f; 引言具体原因网站思路总体 我让AI给个框架1. **项目初始化与依赖安装**2. **定义数据模型**3. **网络请求模块**4. **页面解析模块**5. **数据存储模块**6. **主程序流程** 结尾 引言 最近在做什么呢 建立一套完整的信息输入输出系统 在我上一…

从0搭建一个springboot web系统

要从头开始搭建一个Spring Boot Web系统&#xff0c;你需要遵循以下步骤&#xff1a; 安装Java开发环境&#xff08;JDK&#xff09;和Maven&#xff08;构建工具&#xff09;。创建一个新的Maven项目。在项目的pom.xml文件中添加Spring Boot相关依赖。创建一个主类&#xff0…

Vue之状态管理的简单使用(事件总线(Event Bus),Vuex和若依前端示例)

文章目录 Vue之状态管理的简单使用&#xff08;事件总线&#xff08;Event Bus&#xff09;&#xff0c;Vuex和若依前端示例&#xff09;Vue之事件总线&#xff08;Event Bus&#xff09;的简单使用Vuex进行状态管理的简单使用若依前端代码store状态管理&#xff1a; Vue之状态…

云原生时代下,操作系统生态的挑战与机遇

在云计算快速发展的背景下&#xff0c;服务器操作系统的产业升级&#xff0c;不再局限于物理服务器层面&#xff0c;市场边界扩张&#xff0c;人工智能、大数据、云计算等新技术的发展也对操作系统的灵活度和智能化提出新的要求。在 2023 龙蜥操作系统大会上&#xff0c;龙蜥社…

pytorch学习笔记(十二)

以下代码是以CIFAR10这个10分类的图片数据集训练过程的完整的代码。 训练部分 train.py主要包含以下几个部件&#xff1a; 准备训练、测试数据集用DateLoader加载两个数据集&#xff0c;要设置好batchsize创建网络模型&#xff08;具体模型在model.py中&#xff09;设置损失函…

深入了解C++:底层编译原理

进程的虚拟空间划分 任何编程语言&#xff0c;都会产生两样东西&#xff0c;指令和数据。 .exe程序运行的时候会从磁盘被加载到内存中&#xff0c;但是不能直接加载到物理内存中。Linux会给当前进程分配一块空间&#xff0c;比如x86 32位linux环境下会给进程分配2^32(4G)大小…

vue3页面跳转产生白屏,刷新后能正常展示的解决方案

可以依次检查以下问题&#xff1a; 1.是否在根组件标签最外层包含了个最大的div盒子包裹内容。 2.看看是否在template标签下面直接有注释&#xff0c;如果有需要把注释写到div里面。&#xff08;即根标签下不要直接有注释&#xff09; 3.在router-view 中给路由添加key标识。 …

c# cass10 获取宗地内所有封闭线段的面积

获取面积的主要流程如下&#xff1a; 获取当前AutoCAD应用中的活动文档、数据库和编辑器对象。创建一个选择过滤器&#xff0c;限制用户只能选择"宗地"图层上的LWPOLYLINE对象作为外部边界。提示用户根据上述规则进行实体选择&#xff0c;并获取选择结果。检查用户是…

前端下载导出文件流,excel/word/pdf/zip等

** 一、导入导出接口增加responseType:‘blob’ ** axios({url: 接口,method: post,data&#xff1a;{},responseType: blob });二、导出方法封装 //data 文件流 //fileName 文件名称 /* mineType 文件类型例如&#xff1a;* 下载 Excel : "application/vnd.m…