如何修改String的value值 String深度解读(一)


由一个道题讲起

        大家都知道,String在创建后其value是不可变的,因为它的修饰符是 private final ,赋值后既不可变,比如String a = “a”; a = new String("b"),其实执行完这段代码后,原有a引用指向的内存区域存储的“a”并没有变为b,只不过是引用指向了新声明的内存区域。

        那么问题来了,如果需要你改变 “a” 的值,可以实现吗?

        答案是可以的。

        我这里提供了两种思路,一种是绕过私有变量不可修改的限制,直接修改value[],另一种是直接修改value对应的内存区域。

通过反射修改

        虽然private final修饰的变量不可修改,但是我们可以通过反射绕过java的检查,将其私有变量设为可以访问,直接修改数组的值。

public static void main(String[] args) throws Exception {
  String a = "AAA";
  Class clz = a.getClass();
  //需要使用getDeclaredField(), getField()只能获取公共成员字段
  Field field = clz.getDeclaredField("value");
  field.setAccessible(true);
  char[] ch =(char[])field.get(a);
  ch[0] = 'B';
  System.out.println(a);
}

通过Unsafe修改:

        关于unsafe的使用,我在上一篇文章中已经讲过,请自行阅读。

        -->>《Unsafe基本操作》

public static void main(String[] args) throws Exception {
  String a = "abc";
  String b = "abc";
  Unsafe unsafe = getUnsafe();
  //获取a的实例变量value
  Field valueInString = String.class.getDeclaredField("value");
  //获取value的变量偏移值
  long offset = unsafe.objectFieldOffset(valueInString);
  //value本身是一个char[],要修改它元素的值,仍要获取baseOffset和indexScale
  long base = unsafe.arrayBaseOffset(char[].class);
  //获取value
  char[] values = (char[]) unsafe.getObject(a, offset);


  //通过计算偏移量为value赋值 
  unsafe.putChar(values, base , 'A');
  System.out.println("a:"+a+" b:"+b);
  //将s的值改为 abc
  a = "abc";
  String d = new String("abc");
  System.out.println("a:"+a+" b:"+b);
  System.out.println("d:"+d+" d==a:"+(d==a));
}

        其原理就是通过unsafe,计算出value的偏移量,以及value的首元素地址,通过unsafe直接修改数组value第一个元素的值。

        关于这两个例子其中涉及到的知识点,由于时间太晚,我会在下一篇中给出详细解读。

        如果你还有什么思路,请给我留言。

◆ ◆ ◆  ◆ ◆

关注并后台回复 “面试” 或者  “视频”,

即可免费获取最新2019BAT

大厂面试题和大数据微服务视频

您的分享和支持是我更新的动力

·END·

后端开发技术

追求技术的深度

微信号:后端开发技术
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后端开发技术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值