String类为啥是final的?
我们找到string的jdk源码
1.看到String类被final修饰。这里你就要说出被final修饰的类不能被继承,方法不能被重写,变量不能被修改。
2.看到final修饰的char[]代表了被存储的数据不可更改性。但是:虽然final代表了不可变,但仅仅是引用地址不可变,并不代表了数组本身不会变,请看下面图片
上图说明:数组中的值发生了改变。
上图说明:无论如何修改,数组的地址值不会改变。
综上:所以在这里只有final修饰是不能确保string的不可变性。还需要privite修饰。才能确保不可变性。
- 因为字符串是不可变的,所以是多线程安全的,同一个字符串实例可以被多个线程共享。这样便不用因为线程安全问题而使用同步。字符串自己便是线程安全的。
- 因为字符串是不可变的,所以在它创建的时候HashCode就被缓存了,不需要重新计算。这就使得字符串很适合作为Map中的键,字符串的处理速度要快过其它的键对象。这就是HashMap中的键往往都使用字符串。
除了 String 类,系统类库中还提供了一些其他的不可变类,基本类型的包装类、BigInteger、BigDecimal等等。这些不可变类比可变类更加易于设计、实现和使用,不容易出错且更加安全。另外,要记住并不仅仅是靠一个 final 关键字来实现不可变的,更多的是靠类内部的具体实现细节。
String真的不可变吗?
综上所述,
String
的确是个不可变类,但是真的没有办法改变 String 对象的值吗?答案肯定是否定的,反射机制可以做到很多平常做不到的事情。String str = "123";
System.out.println(str);
Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
char[] value = (char[]) field.get(str);
value[1] = '3'; 执行结果:
123
133
很显然,通过反射可以破坏String
的不可变性。
参考:https://blog.csdn.net/weixin_44946052/article/details/89409188