String
几乎是平时最常用到的对象, 这里记录一下关于它的一些内容
String
到底是如何不可变的?源码中String
对象用于存储字符的属性是这样的private final char value[]
, 它之所以不可变, 首先是因为value
变量是private
修饰的并且没有提供get,set
方法, 因此外部无法修改; 其次value
是被final
修饰的, 表示它是一个常量, 无法修改
String
真的不可变么?String
的值是存在value
数组里的, 虽然value
无法改变, 但是数组里的内容我们可以修改, 比如下面, 就把字符串Hello World
变成了Hello_World
public void testString() throws Exception {
String str = "Hello World";
Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
char[] value = (char[]) field.get(str);
System.out.println(str);
value[5] = '_';
System.out.println(str);
}
String a = "a";
final String fa = "a";
String s1 = "ab";
String s2 = "a" + "b";
String s3 = new String("ab");
String s4 = a + "b";
String s5 = fa + "b";
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(a == fa); // true
System.out.println(s1 == s4); // false
System.out.println(s1 == s5); // true
StringBuilder
// 好的写法
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 100; i++) {
sb.append(i);
}
String str = sb.toString();
// 坏的写法
String str = "a";
for (int i = 1; i <= 100; i++) {
str = str + i;
}
String
不可变, 一般不会有线程安全问题, 现实场景中经常对字符串进行一些操作, 一般是通过StringBuilder
来进行的, 它是非线程安全的; 对应的线程安全版本为StringBuffer
, 它相当于把StringBuilder
的所有方法都加了锁(包括toString
方法).