String Tab
1、String基本特性
-
final修饰、不可继承
-
实现Serializable:可序列化
-
实现Comparable:可排序比较大小
-
jdk8及以前使用final char value[]存储,之后改为byte[]
- 原因:char占两个字节,byte占一个字节,大部分情况下使用的都是拉丁字符(占一个字节)、避免浪费
-
字符串常量池中不会存储相同内容的字符串
-
String Pool是一个固定大小的HashTable,String过多容易hash冲突、链表过长 、tring.intern性能下降
-
设置长度:-XX:StringTableSize
-
String Table默认大小1009(jdk6,设置大小无要求),60013(jdk7)、jdk8开始1009是可设置的最小值
c如果设置最小值小于1009、报错
-
2、String内存分配
-
Java 6及以前,字符串常量池存放在永久代。
-
Java 7 中 Oracle 的工程师对字符串池的逻辑做了很大的改变,即将字符串常量池的位置调整到Java堆内。
所有的字符串都保存在堆(Heap)中,和其他普通对象一样,这样可以让你在进行调优应用时仅需要调整堆大小就可以了。字符串常量池概念原本使用得比较多,但是这个改动使得我们有足够的理由让我们重新考虑在Java7中使用string.intern()。 -
Java8元空间,字符串常量在堆
为什么调整位置?
3、字符串拼接操作
1.常量与常量(常量引用,如final修饰的常量)的拼接结果在常量池,原理是编译期优化
2.常量池中不会存在相同内容的常量。
3.只要其中有一个是变量,结果就在堆中。变量拼接的原理是stringBuilder
StringBuilder拼接字符串与 ‘+’ 拼接字符串差别
- StringBuild的append方式:
- 自始至终只创建一个StringBuilder对象
- 优化:可以根据实际情况,给出一个限定值作为参数来创建构造器,避免多次扩容
- ‘+’拼接的方式:
- 调用了多少次拼接就创建了多少个StringBulider和String对象、导致内存占用过多,GC需要更多时间
4.如果拼接的结果调用intern()方法,则主动将常量池中还没有的字符串对象放入池中,并返回此对象地址。
4、intern()使用
返回的是字符串在常量池中的地址(如果没有该字符串将会加载一个、再返回)
native方法
Interned string就是确保字符串在内存里只有一份拷贝,这样可以节约内存空间,加快字符串操作任务的执行速度。注意,这个值会被存放在字符串内部池(String Intern Pool)。
- jdk1.6中,将这个字符串对象尝试放入串池。
- 如果串池中有,则并不会放入。返回已有的串池中的对象的地址
- 如果没有,会把此对象复制一份,放入串池,并返回串池中的对象地址
- Jdk1.7起,将这个字符串对象尝试放入串池。
- 如果串池中有,则并不会放入。返回已有的串池中的对象的地址
- 如果没有,则会把对象的引用地址复制一份,放入串池,并返回串池中的引用地址
对于程序中存在大量重复字符串、使用intern方法能够接合适呢个内存空间
面试题
new String(“ab”)会创建几个对象?
答案:两个。一个是通过new关键字在堆空间创建的;另一个是字符串在常量池中的对象
拓展:new String(“a”)+new String (“b”)呢?
答案:6个。
new StringBuilder()
new String(“a”)
“a”
new String(“b”)
”b”
new String(“ab”)
注意:常量池中并不存在“ab”
拓展:
拓展:
拓展: