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

相关推荐
musenh2 分钟前
spring学习1
java·学习·spring
专注于大数据技术栈17 分钟前
java学习--Vector
java·学习
sheji341619 分钟前
【开题答辩全过程】以 基于Java的校内美食推荐系统的设计与实现为例,包含答辩的问题和答案
java·开发语言·美食
白典典22 分钟前
解决iTextPDF生成手册时目录页码与实际页码不匹配问题
java·spring·intellij-idea
静心观复25 分钟前
foreach中使用remove踩坑
java
内存不泄露25 分钟前
基于 Spring Boot 的医院预约挂号系统(全端协同)设计与实现
java·vue.js·spring boot·python·flask
袁慎建@ThoughtWorks28 分钟前
如何发布自定义 Spring Boot Starter
java·spring boot·后端
开开心心_Every37 分钟前
强制打字练习工具:打够百字才可退出
java·游戏·微信·eclipse·pdf·excel·语音识别
xiaolyuh12337 分钟前
Redis 核心业务流程
java·redis·spring
BD_Marathon39 分钟前
MyBatis——封装SqlSessionUtils工具类并测试功能
java·windows·mybatis