哈喽!
欢迎各位来到肖肖的猪会飞Java小课堂
关注小猪,一起探索Java的奥妙
文章目录
前言
你们都懂的,哈哈哈,看过我前面文章的友友们都知道(^∀^●)ノシ,我这里总会有个前言。和前面的一样,文章可能有不太完善或者总结不到位的地方,请各位大佬帮我指出哈(@^0^)
那下面我们来正式进入正文——》
1,什么是字符串常量池?
“池”是编程中的一种常见的、重要的提高效率的方式。以后我们还会接触到各种“池”,比如“内存池”、“线程池”、“数据库连接池”等等。
在Java程序中,我们都知道,很多字面类型的常量经常频繁使用,为了使程序的运行速度更快、更节省内存,Java为8种基本数据类型提供了常量池,同样,也为String类提供了常量池----》字符串常量池。
字符串常量池在JVM中是StringTable类,实际是一个固定大小的HashTable(一种高效用来进行查找的数据结构),但是,需要注意的是,不同的jdk版本下的字符串常量池的位置和默认大小是不一样的!!(这里就不细讲了,我这里主要在Java8 HotSpot上来讲解字符串常量池)
有几点问题需要注意的:
(1)在jvm中字符串常量池只有一份,是全局共享的
(2)刚开始的时候字符串常量池是空的,随着程序的不断运行,字符串常量池中的元素会越来越多
(3)当类加载时,字节码文件中的常量池也被加载到jvm中,称为运行时常量池,同时会将其中的字符串常量保存在字符串常量池当中。
(4)字符串常量池中的内容分为两部分------》一部分来自运行时常量池,一部分来自程序动态添加。
2,全面讲解字符串常量池
2.1,直接赋值
代码实例:
从上面的代码来看,返回了一个true值,下面来看它在常量池中是如何进行的----》
通过调试,我们可以看到两个字符串都是由value和hash组成,我们仔细看,两者的value的地址是相同的,这也就说明了,双引号引起来的元素在字符串常量池中只有一份!!
图形解析(哈希值的不画):
2.2,new了String类对象
代码实例:
从上面的代码可以看出,程序输出false
调试:
可以看出,和上面直接赋值的差不多,也是一个value和一个hash,value的地址也是相同的,那为什么输出false呢?
字节码层面解析:
(1)new:在堆上开辟String对象大小的空间,并将对象中成员初始化成0,然后将空间首地址压栈。
(2)dup:将String对象空间的首地址拷贝一份到栈顶备用
(3)ldc:将常量池中的“hello”对象引用拷贝到栈顶
(4)invokespecial:调用String类构造方法,此时要取走hello对象的引用和第一步new的空间String空间的地址
(5)astore1/2:用栈顶元素给s1/s2赋值。
图形解析(哈希值的不画):
3.2,几种特殊的情况
(1)代码实例:
这里输出的是true,可见直接赋值的时候,已经确定了字符串,所以可以是相同的。
(2)代码示例:
此时输出的是false,因为str2和str3是变量,在编译的时候,还不知道里面的内容,是不确定的,所以不同。
3,intern方法
intern是一个native方法(底层使用C++代码实现的),作用是手动将创建的String对象添加到常量池中。(在Java6,Java7和Java8中的实现会有些差别)。
实例代码1:
这里输出的是false,
图形解析:
当加入intern后-------》
代码示例2:
此时输出的是true
图形解析:
以上就是字符串常量池的全部内容,额,,那就这样吧,嘻嘻
本期博客到此结束,希望对你们有用o(〃^▽^〃)o
如果你觉得可以的,可以给小博主一个小小的三连哈,鼓励一下小猪,肝更多的干货给兄弟们!
没有关注的小朋友赶紧关注哈,要不然就找不到我了╰( ̄ω ̄o)
加油哈!!
下期再见~~