String
String 使用 private final char value[]来实现字符串存储,所以String对象创建之后就不能再修改此对象中存储的字符串内容。和c++中的const char[] 类似。
Java把String设成不可变对象最大的原因是效率和安全。
注意:String对象是引用类型,所以,即使不能修改对象内存地址的值,但可以改变引用的对象。对外显示出修改效果。
String a = "abcd";
String b = a;
a = a + "";
// == 是直接比较内存地址
System.out.println(a == b);
System.out.println(a.equals(b));
// 返回
false
true
可以看出字符串a已经改变了引用的地址。
直接使用" "双引号的创建
String s1 = "first";
Stirng s2 = "first";
System.out.println(s1 == s2);
// 返回
true
"first"是编译时期常量,它保存在常量池中。
所以s1 和 s2 都指向常量池中的同一个地址。
用new string("string")的创建
String s1 = new String("first");
String s2 = "first";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
// 返回
false
true
s2 始终创建在堆区,所以s1和s2的内存地址不一样。
但是它们的值一样,可以通过equals()方法判断
用重载的字符串连接符创建
String s1 = "fi" + "rst";
String s2 = "first";
System.out.println(s1 == s2);
// 返回
true
这种方法本质还是和方法1差不多,与此同时还在常量池中新建了"fi" 和"rst"常量。
s1还是储存在常量池中,且和s2是同一个地址。
StringBuilder
本质上,其内部着维护一个char[]字符数组。和c++中的string类型类似。
当字符串增长大于数组长度时会重新申请一个更大的字符数组,但StringBuilder本身的地址没有改变。改变的是内部char[]的地址。
StringBuffer
和StringBuilder大部分功能一样,区别在于StringBuffer是线程安全的。