更多 Java 基础知识方面的文章,请参见文集《Java 基础知识》
String - Immutable Class
public static void main(String[] args) throws Exception {
String s1 = "123";
String s2 = "123";
String s3 = new String("123");
String s4 = new String("123");
// True
// s1 和 s2 都指向常量池 String Pool 中的 123
System.out.println(s1 == s2);
// False
// s3 和 s4 都指向堆 Heap 中的 123
// 存在两份 123,地址不同
System.out.println(s3 == s4);
// False
// s1 指向常量池 String Pool 中的 123
// s3 指向堆 Heap 中的 123
System.out.println(s1 == s3);
}
String s5 = "123";
String s6 = "12" + "3";
// True
// 在编译期,"12" + "3" 被优化为 "123"
// s5 和 s6 都指向常量池 String Pool 中的 123
System.out.println(s5 == s6);
String s7 = "123";
String s8 = "12";
String s9 = s8 + "3";
// False
// 由于有符号引用 s8 的存在,s8 + "3" 在编译期不会被优化
// s9 所指的 "123" 实际存在堆 Heap 中
System.out.println(s7 == s9);
String s10 = "123";
final String s11 = "12";
String s12 = s11 + "3";
// True
// 对 final 变量的访问在编译期会被替换为真实的值
// 因此 s11 + "3" 在编译期被优化为 "123"
// s10 和 s12 都指向常量池 String Pool 中的 123
System.out.println(s10 == s12);
String s13 = "123";
// static String getX() { return "12"; }
final String s14 = getX();
String s15 = s14 + "3";
// False
// s14 虽然为 final,但是是通过方法返回
// 因此 s14 和 s15 只能在运行时确定
// s15 所指的 "123" 实际存在堆 Heap 中
System.out.println(s13 == s15);
String intern() 方法
- 如果常量池 String Pool 中包含该值,则返回常量池中的该对象
- 否则,在常量池 String Pool 中创建该对象并返回
例如:
public static void main(String[] args) throws Exception {
String s1 = "123";
String s2 = new String("123");
// 返回常量池中的 "123"
String s3 = s2.intern();
// False
// s1 指向常量池 String Pool 中的 123
// s2 指向堆 Heap 中的 123
System.out.println(s1 == s2);
// True
// s1 指向常量池 String Pool 中的 123
// s3 指向常量池 String Pool 中的 123
System.out.println(s1 == s3);
}
StringBuilder
- Mutable Class,提供修改字符串的方法,例如:
append(char c)
insert(int offset, char c)
delete(int start, int end)
deleteCharAt(int index)
setCharAt(int index, char ch)
- 线程不安全
StringBuffer
- Mutable Class,提供修改字符串的方法,例如:
append(char c)
insert(int offset, char c)
delete(int start, int end)
deleteCharAt(int index)
setCharAt(int index, char ch)
- 线程安全,Synchronized