一旦被初始化,就不能再被改变;即使修改,也是新的对象
String s = "Hello";
s = "你好";
为了满足不可变对象,Java语言要求遵守以下5条原则:
我们来看一下源码:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
}
从源码可以看出,String满足不可变对象的5条原则,源码解析:
综上,value一旦产生,内存地址就根本无法被修改。
既然String是不可变的,好像内部还有很多substring, replace, replaceAll这些操作的方法。好像都是对String对象改变了,解释起来也很简单,我们每次的replace这些操作,其实就是在堆内存中创建了一个新的对象。然后我们的value指向不同的对象罢了。
String str = “Hello world!”;
str = str.replace("world", "World...");
真的不能改变String吗?别忘了反射机制,在通常情况下,他可以做出一些违反语言设计原则的事情。
通过反射来改变String:
public class StringDemo {
public static void main(String[] args) {
String str = "Hello";
System.out.println(str);
try {
// 通过反射获取内部的value字符数组
Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
char[] value;
value = (char[]) field.get(str);
// 把字符串第一个字符H变成小写
value[0] = 'h';
System.out.println(str);
} catch (Exception e) {
e.printStackTrace();
}
}
}