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如果找到了就返回字符串常量池的引用,如果没有找到就会创建(创建流程与上文讲述相似)

相关推荐
JIngJaneIL1 小时前
基于Java非遗传承文化管理系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot
南部余额1 小时前
踩坑与解惑:深入理解 SpringBoot 自动配置原理与配置排除机制
java·spring boot·自动配置原理·import
木鹅.3 小时前
LangChain4j
java
永远都不秃头的程序员(互关)3 小时前
Java核心技术精要:高效实践指南
java·开发语言·性能优化
CoderYanger3 小时前
动态规划算法-子序列问题(数组中不连续的一段):28.摆动序列
java·算法·leetcode·动态规划·1024程序员节
代码栈上的思考4 小时前
深入解析Spring IoC核心与关键注解
java·后端·spring
Mai Dang4 小时前
SpringBoot4用Swagger
java
geekmice5 小时前
实现一个功能:springboot项目启动将controller地址拼接打印到txt文件
java·spring boot·后端
老华带你飞5 小时前
旅游|基于Java旅游信息系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot·旅游