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方法).