String真的不能修改?
String类有final修饰符,因此String是无法被继承的,String定义的量是常量,字符串一旦被创建,内容和长度就无法修改,因此为了方便对字符串的修改提供了String buffer和String builder两种方法。
肯定会有同学反驳我,明明我平时写的时候想怎么改就怎么改!!!比如下面这个:
这不是啪啪打脸了吗~
No~No~No~
请看下面代码
为什么会出现这样的现象?
这是因为是s1存储的只是value的地址(在这里你可以直接理解为哈希值)而非字符串本身,这里所谓的”修改“只是又在内存新开辟了一块内存,存储”dsgh“,然后将s1指向是,也就是说:没有修改字符串内容,而是修改的s1的指向,1956725890存储的永远都是abc,这是不变的。
那到底应该怎么改?
由于value属于String内部的私有属性,外部是无法直接修改的,我们这里使用反射去进行修改
String s1 ="abc";
//输出字符串以及哈希值
System.out.println("修改前字符串内容为:" + s1 +" hash值为:" +System.identityHashCode(s1));
//获得Class的实例化对象
Class strclass =s1.getClass();
//获取String类中的value属性
Field field = strclass.getDeclaredField("value");
//打开权限
field.setAccessible(true);
//获取字符串内容并将其存入字符数组中
char[] value =(char[])field.get(s1);
//输出修改前的字符数组
System.out.println("修改前的value是:" + Arrays.toString(value));
//修改字符
value[0] = 'f';
value[1] = 'g';
value[2] = 'p';
//再次输出字符串以及哈希值
System.out.println("修改后字符串内容为:" + s1 +" hash值为:" +System.identityHashCode(s1));
这才是真正的修改!
String buffer和String bulider
前面我们利用反射可以实现修改,可是每次这么改也太麻烦了,于是java提供了String buffer和String bulider两种方法修改字符串
两者区别(高频面试考点):
- 二者在功能和作用上完全一致
- String buffer方法采用synchronized关键字就是(加锁),所以是线程安全的,String bulider没有所有线程不安全
- 但也是因为没有加锁,不用每次判断锁,String bulider效率更加快,String buffe则慢一些