每天进步一点点,距离大神又进一步!
前言
很多人不以为然的认为:这很简单,已经很熟悉了。但很多东西表面看上去很简单,若深入去剖析,你会发现一个
源码剖析
要去了解一个类,必须得从源码开始。
使用修饰说明是从成员可以看出,是由存储的。
再看看下面一段源码:
从这几个方法可以看出,方法返回都是或者,说明的任何方法都
谨记:
字符串常量池
1.相关jvm内存模型
jvm内存模型分为:jvm栈(简称成为),堆,方法区,本地方法栈,程序计数器
这里只简单说明说
(1)栈:存放,一个会对应一个,栈帧中存储着等信息
:存放各种(boolean,byte,int等)和。
(2)堆:存储和(所有new的对象)
(3)方法区:存储类的信息(类的版本,字段,方法等描述信息),
:存储jvm编译时产生的字面量(如文本字符串,声明为final的常量值等)和符号引用(类和接口的全限定名,字段名称和描述符,方法名称和描述符)
:在常量池中,有一张固定长度的表用来存储字符串值,称其为
2.String在内存中的存储
来看下面代码:
PS:
1.首先会在栈中生成引用,检查是否存在字符串,不存在则在其创建一个字符串
2.字符串池中已存在字符串,则在执行时返回字符串常量池中的引用,则是
3.同样,字符串常量池中已存在字符串,无需添加新的字符串至字符串常量池中,但此处使用了,则会强制在中生成一个对象。则
如下图:
3.String创建方式对比(1) 编译期创建a.字面量赋值
分析:是常量会在编译器被创建,存储在字符串常量中
b.字面量”+“字面量
分析:会在编译时被优化,看作,
则
c.字面量”+“final字符串引用
分析:对于final修饰的变量,它在编译时被解析为常量值,存储到自己的常量池中,则
和效果相同 即
(2)运行期创建a. new String()
分析:
b.字符串引用"+"字符串引用
分析:引用相加需要在运行期进行运算,需在堆中创建新对象
执行步骤:
1.编译时,在字符串常量池创建和对象
2.运行时,在堆中创建对象a和一个对象b,a + b通过StringBuilder的append()方法进行运算,在通过StringBuilder的toString()方法返回一个新的对象,让c指向这个对象
这段代码中,在字符串常量池中创建了两个对象,在堆中创建了3个对象
c.字面量"+"字符串引用
分析:与上一个例子b中相同
d.方法返回赋值
分析:虽然s1使用了修饰,但是它是通过调用getB()返回赋值的,那么它的值只能在运行期间确定,所以c中指向的是堆中的,即
嘿!老铁,跑快点!路,还很长...
成神之路,一路有我!
如有错误,请指正!欢迎点赞与分享!
领取专属 10元无门槛券
私享最新 技术干货