内存分析:字符串常量池
图片内容源自B站黑马Java基础公开课
给定以下字符串实例化的代码段,分析内存中的数据流动
一、绘制内存结构图
二、字符串实例化
String str1 = "abc";
- 栈中开辟main方法栈帧(图中省略),在栈帧中开辟一段名为str1的地址空间,用于保存字符串实例的地址
- 堆中实例化一个字符编码数组,数组长度为字符串长度,内容为字符串中每个字符的编码值(图中以ASCII码为例)
- 堆中有一块专门存储字符串对象的区域:字符串常量池。在其内部实例化一个String对象,将上述字符编码数组的首地址赋值给String对象,相当于字符串常量池中的一个字符串对象指向一个字符编码数组
- 将该字符串的地址赋值给栈帧中的str1变量,相当于变量str1指向/引用了该字符串对象
String str2 = "abc";
- 在栈帧中开辟一段名为str2的地址空间,用于保存字符串实例的地址
- JVM首遍历字符串常量池中储存的字符编码数组(当然,这个过程在上一句中也会执行),一旦发现存在与即将赋值的字符串相同的实例,那么直接将相同字符串实例在堆内存中的地址值赋值给str2变量
三、字符数组实例化
char[] charArray = {'a', 'b', 'c'};
参考数组的内存分析部分,在堆内存中实例化一个字符数组,将其首地址赋值给栈内存中的charArray变量
四、字符串对象实例化
String str3 = new String(charArray);
- 利用字符数组实例化字符串对象时,JVM首先会将目标字符数组转化为字符编码数组
- 一切new出来的对象都在堆内存中。参考对象的内存分析部分,JVM在堆内存中实例化一个String类对象,将上述字符编码数组的首地址赋值给字符串对象
- 将字符串对象的地址赋值给栈帧中的字符串类型变量str3
五、总结
- 对于引用数据类型,== 进行的是地址值的比较
- 双引号 “” 直接引上的字符串常量池中,new 出来字符串对象的不在常量池中