源码
在IDEA中找到,String的源码
// Java 11
public final class String implements Serializable, Comparable<String>, CharSequence {
@Stable
private final byte[] value;
private final byte coder;
private int hash;
private static final long serialVersionUID = -6849794470754667710L;
...
}
- String类是被
final
修饰的,意味着不能被继承。 - String类实现了
Serializable
接口,意味着它可以被序列化;序列化可以理解为版本号的迭代,通过serialVersionUID记录。 - String类实现了
Comparable
接口,意味着最好不要使用==
来比较两个字符串是否相等,应该使用compareTo()
方法比较 - StringBuffer、StringBuilder和String一样,都实现了
CharSequence
接口。由于String是不可变的,所有字符串拼接的时候尽量就考虑他们。 - Java 9以前,String是用char数组实现的,之后改成了byte数组实现,并增加了coder来表示编码。在Latin1字符为主的程序里,可以把String占用的内存减少一般。改进在节省内存的同时也增加了编码检测的开销。
- 每一个字符串都有一个hash值,大概率不会重复,所以String很适合来作为HashMap的键值。
Latin1
Latin1是 ISO-8859-1 的别名,有些环境下写作Latin-1。. ISO-8859-1编码是单 字节 编码,向下兼容 ASCII ,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是 控制字符 ,0xA0-0xFF之间是文字符号。
CharSequence接口
public interface CharSequence
CharSequence是char值的可读序列。
该接口提供对许多不同类型的char序列的统一,只读访问。
CharSequence是一个描述字符串结构的接口,在这个接口里面一般发现有三种常用的子类:
(1)Stirng类
(2)StringBuffer类
(3)StringBuilder类
String的不可变性
- String 类被 final 关键字修饰,所以它不会有子类,这就意味着没有子类可以重写它的方法,改变它的行为。
- String 类的数据存储在 byte[] 数组中,而这个数组也被 final 关键字修饰了,这就表示 String 对象是没法被修改的,只要初始化一次,值就确定了。
为什么要这样设计?
第一,可以保证 String 对象的安全性,避免被篡改,毕竟像密码这种隐私信息一般就是用字符串存储的。
第二,保证哈希值不会频繁变更。毕竟要经常作为哈希表的键值,经常变更的话,哈希表的性能就会很差劲。
第三,可以实现字符串常量池。
不管是截取、拼接,还是替换,都不是在原有的字符串上进行的,而是重新生成了新的字符串对象。也就是说,这些操作执行过后,原来的字符串对象并没有发生改变。
String 对象一旦被创建后就固定不变了,对 String 对象的任何修改都不会影响到原来的字符串对象,都会生成新的字符串对象。