JVM进阶-面试字符串拼接底层(字符串常量池)

前言

我们大家都知道JVM中有一个常量池的概念,他的出现是为了省略我们一些基本变量重复创建导致空间浪费,我们在创建变量时变量将存入常量池中在下次创建我们就会直接引用字符串常量池中的对象。

但常量池究竟是如何运作的我们接下来看看吧

首先在阅读这篇文章的时候需要对JVM内存模型有一定的了解

示例

java 复制代码
String a = "aa";
String b = "a"+"a";
String c = "a";
String d = "a"+c;


sout(a == b); // true
sout(a == d); // false

====================================================

String a = new StringBuilder("aa").toString();
String b = "aa";
sout(a == b); //false

==================================================

String a = new StringBuild("aa").append("bb").toString();
String b = "aabb";
sout(a == b); //true

字符串常量池

在我们使用String b = "XXX"或者是aa("XX")这种直接引号形式静态声明字符串,都会向常量池中添加数据

1.6及以前有着永久代的概念(存储字符串常量池、对象class、静态变量)

JDK1.6后字符串常量池就到了栈内存中、永久代被元空间替代了

字符串常量池其实很像HashTable,key中存储对象指针,value中存储对象在堆空间中的内存地址,在我们程序中对象引用的就是我们的字符串常量池中的对象指针。!!!在每一次创建这种静态声明形式会先在常量池中遍历一遍找到了与他相同的对象就直接引用、没有找到就直接创建(这个创建又会遍历一次堆内存发现又相同的对象就直接引用到字符串常量池中,没有就自己创建)!!!

结合示例

java 复制代码
String a = "aa";
// 这一行在JVM编译的时候会对其进行优化变为:String b = "aa"
String b = "a"+"a";

在第一行执行的时候JVM中的字符串常量池还没有这个aa值的对象,那么在第一行会在堆内存中创建一个aa的字符串对象并将他记录到字符串常量池中

第二行执行的时候JVM先遍历字符串常量池,发现找到了那么就直接指向字符串常量池

我们可以发现他们引用的都是一个对象所以a、b等值

Stirng a = "a"
String b = "a" + a;

这一种形式JVM没有办法在编译的时候优化
在执行b的时候JVM会底层调用创建一个StringBuile然后将两个字符串都append进去然后再toString所以a、b不等值
java 复制代码
String a = new StringBuilder("aa").toString();
String b = "aa";
sout(a == b); //false

在这个理解起来会复杂一点,但是也非常简单

第一行:
    1.首先发现我们有一个字符串静态声明,这里会记入字符串常量池中
    2.new StringBuilder()会创建一个aa的StringBuilder对象
    3.使用StringBuild.toString()在底层会使用new String()所以这里又创建了一个变量
    
第二行:这里直接拿到我们字符串常量池中的数据

到这里我们就很好理解了a为toString后的值,b为字符串常量池中的值,所以a、b不等值
java 复制代码
String a = new StringBuild("aa").append("bb").toString();
String b = "aabb";
sout(a == b); //true

这个就然大家来判断一下吧
主要就是,在创建添加字符串常量池中会寻找堆中有没有相同的对象如果有就直接引用

后言

其他的基本类型的常量池就很简单了

Boolean在程序中就定义好了

Integer 在创建的时候就存储-128~127的值

intern

比如StringA.intern()

这个方法就是从字符串常量池中获取与这个String值相同的key如果找到了就返回字符串常量池的引用,如果没有找到就会创建(创建流程与上文讲述相似)

相关推荐
xbgRS2 小时前
springboot的自动装配
java·spring boot
嘻哈∠※9 小时前
0061基于 SpringBoot 的投稿与稿件处理系统设计与实现
java·spring boot·后端
白狐_79810 小时前
408数据结构第8章:排序②——性质对比秒杀、场景选择与外部排序
java·数据结构·算法
zander25811 小时前
LeetCode 84:柱状图中的最大矩形——单调栈如何确定左右边界
java·数据结构·算法
码匠许师傅11 小时前
【C++ 面试真题】聊聊 C++ 的拷贝构造与拷贝赋值
java·c++·面试
极创信息13 小时前
系统安全隐患全方位排查方案:标准化渗透测试全流程
java·opencv·struts·数据挖掘·eclipse·语音识别·hibernate
汉字萌萌哒13 小时前
2019CCF-CSP入门级C++试题解析
java·开发语言·c++
喜欢的名字被抢了13 小时前
程序出问题怎么查,以及如何让它不掉线
java·运维·数据库
数据知道14 小时前
反序列化漏洞:Java、PHP、Python 三条线各讲透
java·网络·python·安全·网络安全·php
2601_9499506314 小时前
Java 面试准备,用练题簿把“背过八股”变成“真正会答”
java·开发语言·面试·刷题·小程序推荐