public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
}
String类的值是保存在value数组中的,并且是被private final修饰的
final关键字的作用有如下几种
在Java中数组也是对象,数组即使被final修饰,内容还是可以改变的
所以我们说String类是不可变的。
而很多方法,如substring并不是在原来的String类上进行操作,而是生成了新的String类
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
字符串常量池可以节省大量的内存空间。如果String类可变就不可能有字符串常量池
字符串常量池放在哪?
jdk1.7之前的不讨论,从jdk1.7开始,字符串常量池就开始放在堆中,然后本文的所有内容都是基于jdk1.8的
下面这个代码还是经常被问到的
String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
String str4 = new String("abc");
// true
System.out.println(str1 == str2);
// false
System.out.println(str1 == str3);
// false
System.out.println(str3 == str4);
解释一下上面代码的输出,Java中有2种创建字符串对象的方式
String str1 = "abc";
String str2 = "abc";
// true
System.out.println(str1 == str2);
采用字面值的方式创建一个字符串时,JVM首先会去字符串池中查找是否存在"abc"这个对象的引用
如果不存在,则在堆中创建"abc"这个对象,并将其引用添加到字符串常量池(实际上是将引用放到哈希表中),随后将引用赋给str1
如果存在,则不创建任何对象,直接将池中"abc"对象的引用返回,赋给str2。因为str1、str2指向同一个对象,所以结果为true。
String str3 = new String("abc");
String str4 = new String("abc");
// false
System.out.println(str3 == str4);
采用new关键字新建一个字符串对象时,JVM首先在字符串池中查找有没有"abc"这个字符串对象的引用
如果没有,则先在堆中创建一个"abc"字符串对象,并将引用添加到字符串常量池,随后将引用赋给str3
如果有,则不往池中放"abc"对象的引用,直接在堆中创建一个"abc"字符串对象,然后将引用赋给str4。这样,str4就指向了堆中创建的这个"abc"字符串对象;
因为str3和str4指向的是不同的字符串对象,结果为false。
String类在被创建的时候,hashcode就被缓存到hash成员变量中,因为String类是不可变的,所以hashcode是不会改变的。这样每次想使用hashcode的时候直接取就行了,而不用重新计算,提高了效率
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** Cache the hash code for the string */
private int hash; // Default to 0
}
由于String类不可变的特性,所以经常被用作HashMap的key,如果String类是可变的,内容改变,hashCode也会改变,当根据这个key从HashMap中取的时候有可能取不到value,或者取到错的value
不可变对象天生就是线程安全的,这样可以避免在多线程环境下对String做同步操作
[1]https://mp.weixin.qq.com/s?src=11×tamp=1592637033&ver=2411&signature=alSwI0tpXmnpwBII3UYs1lFZqTk2rx1VymKrT-tfFt86HNwLbLHfMqxloqZhERqHtwi-Ezrx6ksZ-hL19oc0xbqVzXw2yicU77LuqYkFMBlYoBTohvdysefGXMHY6W9l&new=1
好文
[2]https://www.ershicimi.com/p/72759faff05aeb5279ffbec79e6a7b52