本文简单讲解Java中那些String引用和字符串常量池的关系
什么是String
什么是字符串常量池
根据源码可知,字符串String对象的底层是char[]数组来存储数据,也就是String对象中包括了char[]数组对象。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
....
}
那么我们来捋清字符串和字符数组的关系
char[] arr = new char[]{'0','1'};
JVM会在堆空间生成一个数组对象,arr变量就指向这个数组对象
String s = "01";
JVM会先在字符串常量池里找到"01"对应的字符串对象
如果没有找到那么就会创建字符串对象和字符数组对象,并会存到字符串常量池,然后将字符串对象引用赋值给变量s;
如果找到就拿到“01”字符串对象的引用,直接赋值给变量s。
当给s修改字符串内容时,
s = "10"
由于字符串对象中的char[]是final修饰的,也就是不可变的,因此当s改变字符串的时候,会重新赋值,而不是去修改原字符。也就是JVM会创建新的“10”字符串对象和字符数组对象,然后把新的字符串对象的引用赋值s。
注意区分两个东西:字符串对象,字符数组对象;字符串对象中引用着字符数组对象;
全局字符串常量池,也就是在整个JVM环境是共享的,起到缓存的作用,缓存的是字符串String对象,存储的形式是KV对(HashTable)。字符串String是最常用的数据类型之一,为了避免字符串频繁创建和销毁的开销,使用字符串常量池对字符串对象复用,能够提高程序执行的性能。JVM在读写字符串的时候都会先从全局字符串常量池中操作,有就直接用,没有则创建。
接下来,我们结合例子说明常见的几种情况
例子1:
String s = "01";
JVM会先在字符串常量池找到“01”字符串对象,
如果找不到就创建新的“01”字符串对象和字符数组对象,然后再把字符串对象引用赋值s;
如果找到了就拿到“01”的字符串对象的引用,赋值给变量s。
例子2:
String s = new String("01");
// 使用到String的构造方法如下:
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
JVM先会定位到“01”变量,然后从字符串常量池中找到“01”,
如果找到就拿到字符串对象的引用赋值给original;
如果找不到就会在堆空间创建“01”的字符串对象和字符数组对象,把字符串对象引用赋值给original;
然后执行到new String(),在堆空间创建新字符串对象并把引用赋值给s,又从字符串常量池找到“01”,拿到的就是字符串对象original,最后把字符串对象original的char[]的引用赋值给新字符串对象s的char[]。
例子3:
String s1 = "01";
String s2 = "01";
s1:JVM会定位到“01”,然后从字符串常量池中找,如果找到直接用,把字符串对象引用赋值给s1;如果找不到则创建“01”的字符串对象和字符数组对象,再把字符串对象引用赋值给s1;
s2:JVM也会定位到“01”,然后从字符串常量池中找,已经存在了“01”字符串对象,那么把直接赋值s2。
所以当s1==s2比较时,结果会返回true
例子4:
String s1 = new String("01");
String s2 = new String("01");
// 使用到String的构造方法如下:
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
JVM会先定位到“01”,然后在字符串常量池中找,如果找到直接拿到引用,赋值给original,如果没有找到则创建“01”新的字符串对象和字符数组对象,然后把字符串对象引用赋值给original;
s1:执行第一个new String(),创建新字符串对象并把引用赋值给s1,然后从字符串常量池中找到“01”的字符串对象,在“01”字符串对象中找到字符数组对象引用,赋值给s1字符串对象的字符数组对象
s2:同理s1
好啦,以上就是本文的全部内容。学习底层知识可以帮忙我们平常在使用它或遇到困难时,有比较好的理论基础和认知,甚至利于分析问题根本。一起加油吧!