string源代码如下
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[];
//...
}
何为不可变:个人理解就是不对外/对内 提供修改接口
用string解释就是,给一个已有字符串"abcd"第二次赋值成"abcedl",不是在原内存地址上修改数据,而是重新指向一个新对象,新地址。
实现:用privite、final修饰,其中final保证私有且未提供修改接口的属性的初始化
问题:为什么还要在此基础上 将string类用final呢?
答:无论一个属性用什么关键字修饰 private或final,都是可以被反射强行修改,对string类加上final,是防止有人恶意继承string并修改string的不可变性,造成string似乎可变的情景(虽然是子类,但是开发时不注意的话,由于多态的特性,很容易出现问题)。另外,jdk自带的string不可变除了private、final关键字修饰外,还有工程师小心翼翼的在后续开发中,不暴露有关修改value[]的接口。
示例如下:
public final class MyClass {
private final String privateField;
public MyClass(String privateField) {
this.privateField = privateField;
}
public String getPrivateField() {
return privateField;
}
}
public class ReflectiveModificationExample {
public static void main(String[] args) {
// 创建一个对象
MyClass myObject = new MyClass("Hello");
// 使用反射修改私有属性
try {
// 获取Class对象
Class<?> myClass = myObject.getClass();
// 获取私有字段
Field privateField = myClass.getDeclaredField("privateField");
// 设置访问权限,使得可以修改私有字段
privateField.setAccessible(true);
// 修改私有字段的值
privateField.set(myObject, "fine");
// 打印修改后的值
System.out.println( myObject.getPrivateField());
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
结果为:fine
参考文章:如何理解 String 类型值的不可变? - 知乎 (zhihu.com)、Java基础常见面试题总结(中) | JavaGuide