文章大纲创建字符串内存分配图
“+”拼接字符串内存分配图
1 创建字符串
众所周知,Java 中有两种字符串的创建方式。
使用双引号创建的字符串,见下面代码:
String test = "ab";
字符串 “ab” 会直接出现在字符串常量池中。
JDK6的版本,常量池在持久代 PermGen 中分配;
JDK7的版本,常量池在堆内存 Heap 中分配;
本文的内存分配图都是基于JDK7以上的版本。
而通过 new String() 的方式创建的字符串,如下所示:
String test = new String("ab");
字符串 “ab” 同样会出现在字符串常量池中,同时在堆内存中也会分配一块空间存放字符串 “ab”。
2 拼接字符串"+"
当字符串遇上了 “+” 号,内存的分配情况开始变得奇怪且有趣了。
案例2-1
String test = "ab" + "cd";
案例 2-1 这种情况编译器会直接优化成 “abcd”, 等价于下面代码:
String test = "abcd";
案例2-2
String ab = "ab";
String cd = "cd";
String test = ab + cd; // @1
案例 2-2 中 @1 这里实际上是使用 StringBuilder.append 来完成字符串的拼接, 所以在堆内存中会存在一个 “abcd”, 但是在字符串常量池中是不会有 “abcd” 的。
代码执行完之后,字符串常量池中的 “ab” 和 “cd” 也会保留下来。
案例2-3
final String ab = "ab";
final String cd = "cd";
String test = ab + cd; // @1
案例 2-3 这种情况实际上,因为加上了关键字 final,所以 @1 等价于下面代码,也就是回到了案例 2-1 的情况:
String test = "ab" + "cd";
此时的内存分配图如下,和案例 2-1 还是有点区别的:
案例2-4
String ab = new String("ab");
String cd = new String("cd");
String test1 = ab + cd;
案例 2-4 这种情况,具体的内存分配无需多说了,这里值得留意的点是,字符串常量池是不会有 “abcd” 的。
案例2-5
String ab = new String("ab");
String test1 = ab + "cd";
案例 2-5 字符串常量池同样是不会有 “abcd” 的。
总结
到这里,我们就算分析为 “+” 拼接字符串的情况了,虽然内存分配图看起来很复杂,但是总结起来也挺简单的
只有下面这两种情况,拼接的字符串 “abcd” 才会出现在常量池中:
两个引号 "ab" + "cd"
两个final final + final
你以为这就结束了? 其实正戏才刚刚开始。
当字符串用上了 String#intern 后,难度再次升级!
先容我缓缓,咱们下篇见。
往期回顾Kafka玩出植物大战僵尸即视感——Topic为什么要分区mp.weixin.qq.com一张图理解Kafka时间轮(TimingWheel),看不懂算我输!mp.weixin.qq.comJava中的队列是怎么支撑起多人运动的?mp.weixin.qq.comJava线程池的故事2, 四个花瓶mp.weixin.qq.com画图理解Java Integer的“值传递”mp.weixin.qq.com
记得关注公众号"字节武装"哦!!!