您的位置:首页 > 其它

JVM中的String Table

2020-07-21 22:46 232 查看

String Table

底层结构

String:字符串;使用双引号 “ ” 引起来表示

声明方式是final,不可被继承

jdk 1.8 String的底层实现是char[]

jdk 1.9 String的底层实现是byte[]

目的是为了节约一些空间

String 是不可变的字符序列

特性字符串

1、字符串常量池不会存储相同内容的字符串

2、String 对应的String 常量池对应的是一个固定大小的Hash Table。HashTable的特性导致了特性1

String 的内存分配

Java 6以前,字符串常量池存放在永久代

Java 7,字符串常量池存放在 Java 堆中

Java 8以后,存放在元空间中

字符串的拼接

字符串的拼接操作

1、常量与常量的拼接结果在常量池,原理是编译器优化,编译时期,直接变成拼接后的字符串并存入字符串常量池中。

2、常量池中不存在相同内容的常量

3、只有拼接时其中有个对象是变量,结果就保存在堆中。

4、如果拼接的结果调用intern() 方法,则主动将常量池中还没有的字符串对象放入池中,并返回此对象地址。

效率对比

通过StringBuilder的append() 的方式添加字符串的效率远高于使用String的字符串拼接。

原因:

StingBuilder的append()的方式:自始至终都只创建一个StingBuilder对象

字符串拼接的方式:创建多个对象,一方面内存读写次数过多,一方面是可能会调用GC,占用线程运行时间

intern() 的使用

如果不是用双引号声明的String对象,可以使用String提供的intern() 方法,intern 方法会从字符串常量池中查询该字符串是否存在,若不存在则放入常量池。

目的是确保在JVM内存中,字符串只有一份拷贝。节约内存空间。

问题1、:String s=new String(" 什么是快乐 ");语句中创建了几个对象?

:创建了两个对象:一个是 “ new”语法在堆中的对象。一个是“什么是快乐”创建在字符串常量池中。变量s存放在局部变量表里

问题2、String s =new String (“什么是”)+new String(“快乐”);语法中创建了几个对象呢

答: 创建了5个:1、StringBuilder对象(涉及到字符串的拼接)2、new String 对象 3、字符串常量池中的“a” 4、new String 对象 5、字符串常量池中的“b” 深层剖析,StringBuilder 中的toString方法new了一个String对象。

注意,此方法生成的字符串 S 不在字符串常量池中!!

问题三3

S与S 2 的原因:s指向的是堆中的一个地址。s1指向的是字符串常量池中的一个地址。两个地址不一样 都为 false

S3 与S4的原因:JDK 版本对于内存改变和intern方法内容的变化:

​ jdk 6 中:字符串常量池存放在永久代、不在堆中。当字符串不在常量池时,intern方法会生成一 个字符串放入池中,此时变量地址指向并不一样:一个在堆中、一个在字符串常量池中

​ jdk 7/8 后:字符串常量池存放在堆中的老年代中。为了节约堆空间,intern()方法发生变化:不 在创建新的对象放入常量池中,而是创建一个指向堆对象的引用。

总结:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: