对于String而言,因其独特的结构以及在实际工程中的重要作用,详细了解其底层运行机制十分重要。主要有一下几个方面
- 底层实现,为什么不可变
- 扩展类
- 内存存储机制(字符串常量池)
- intern()函数
底层实现
概念
不可变的,每一次修改实际上生成新的字符串,并且该字符串的值是修改后的值。new String都是在堆上创建字符串对象
String 被声明为 final,因此它不可被继承。(Integer 等包装类也不能被继承)
在 Java 8 中,String 内部使用** char 数组**存储数据。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
}
String如何保证不可变?
- value 数组被声明为 final,这意味着 value 数组初始化之后就不能再引用其它数组
- 并且String 内部没有改变 value 数组的方法,因此可以保证 String 不可变。
类如何实现不可变
- 所有域是final的,并且是private,并且提供修改对象状态的方法
- 把类声明为final,保证类不可以被扩展,不可以被子类修改方法的行为从而改变域的值
不可变的好处
1、线程安全
String 不可变性天生具备线程安全,可以在多个线程中安全地使用。
2、类的实现简单
由于对象是不可变的,天然支持线程安全,因此不用使用额外的代码来保证线程安全
扩展类
String、StringBuilder、StringBuffer的区别
- 可变性
- String不可变
- StringBuilder、StringBuffer可变
- 线程安全
- String不可变,因此是线程安全的
- StringBuilder不是线程安全的
- StringBuffer 是线程安全的,内部使用 synchronized 进行同步
StringBuilder、StringBuffer的区别
-
StringBuffer 与 StringBuilder 中的方法和功能完全是等价的,
-
StringBuffer 中的方法都采用了 synchronized 关键字进行修饰,因此是线程安全的,
而 StringBuilder 没有这个修饰,可以被认为是线程不安全的。 -
在单线程程序下,StringBuilder效率更快,因为它不需要加锁,不具备多线程安全
而StringBuffer则每次都需要判断锁,效率相对更低
内存存储机制
一.创建时底层逻辑
第一种创建方式
//字面量“hello”存入字符串常量池,str存储“hello”的地址,此时没有堆中对象
String str="hello";
第二种创建方式