6. String Table
6.1 String的基本特性
- String声明为final,不可被继承
- 实现了Serializable接口:支持字符串序列化
- 实现了Comparable接口:可以比较大小
- jdk8之前定义final char[] value储存字符串数据,jdk9之后用byte[]
String的不可变性。
字符串常量池是不会存储相同内容的字符串。
-XX:StringTableSize
设置StringTable的长度。(JDK8最小值为1009)
String的String Pool是固定大小的HashTable
6.2 String的内存分配
- 双引号声明出来的String对象会直接储存在常量池
- 使用String提供的intern()方法。
字符串常量池在堆中。
6.3 字符串拼接操作的面试题讲解
字符串拼接操作
- 常量与常量的拼接在常量池中,原理是编译期优化
- 常量池中不会存在相同内容的常量
- 只有其中有一个是变量,结果就在堆中(new String(),具体的内容就是拼接的结果)。变量拼接的原理是StringBuilder
- 如果拼接的结果调用intern()方法,则主动将常量池中还没有的字符串对象放入池中,并返回此对象地址。
intern()
:判断字符串常量池中是否存在该字符串的值,如果存在则返回常量池的地址,如果不存在,则放入常量池并返回地址。
== 和 equals()
==
:直接比较两个对象的堆内存地址equals()
:对于Object而言是一样的,但是这个方法可以重写,所以可以写成与内容一致。
拼接的底层细节
/*
String s1="a";
String s2="b";
String s3=s1+s2;
String s4="ab";
*/
/*
s1+s2的细节:
StringBuilder s=new StringBuilder();
s.append("a");
s.append("b");
s3=s.toString(); //toString()类似于new String("ab");
sout(s3 == s4);//true
*/
拼接操作和append的效率
拼接操作的效率会比append远远的低。
StringBuilder的append()方式的好处:自始至终只创建过一个StringBuilder的对象
String的字符串拼接方式:创建多个StringBuilder和String对象。内存占用更大,如果进行GC,需要花费格外时间。
在实际开发中,如果基本确定前前后后添加的字符串长度不高于某个限定值highlevel的情况下,建议使用StringBuilder s=new StringBuilder(highlevel)
intern()方法的使用
String{
public native String intern();
}
String myInfo=new String("I love NUAA").intern();
//intern()方法会从字符串常量池中查询当前字符串是否存在,如果不存在则将当前字符串放入常量池中,返回的是该字符串常量池中的地址
保证String变量s指向的是字符串常量池中的数据?
String s="wangguofu";
String s=new String("wangguofu").intern();
String s=new StringBuilder("wangguofu").toString().intern();
intern()更加深入理解
public class StringIntern1{
//在jdk6是一种结果 在jdk7/8的时候是另外一种结果(由于字符串常量池存储的内存位置发生了变化)
main(){
String s=new String("1");
s.intern();
String s2="1";
sout(s==s2);//jdk6: false jdk7/8:false
String s3=new String("1")+new String("1");
s3.intern();
String s4="11";
sout(s3==s4);//jdk6:false jdk7/8:true
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5qZiEmWb-1615212272653)(https://i.loli.net/2021/03/08/87UBrGgh4MpYqvd.png)]
new String(“ab”)会创建几个对象?
会创建两个对象。(可以看字节码)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f10k1IPl-1615212272655)(https://i.loli.net/2021/03/08/7iR9fuJqHEGYv1t.png)]
一个是String的对象,一个是字符串常量池"ab"的对象
new String(“a”)+new String(“b”)会创建几个对象?
![image-20210308213837152](https://i-blog.csdnimg.cn/blog_migrate/5bb0235c9a2595839cdd36576da87124.png)
对象1:new StringBuilder()
对象2:new String(“a”)
对象3:字符串常量池中 “a”
对象4:new String(“b”)
对象5:字符串常量池中的"b"
深入剖析:
对象6:StringBuilder.toString()
强调一下toString()方法的调用,在字符串常量池中没有"ab"(这个toString方法的new String()传参的是char[])