Java不改变内存地址修改字符串内容

之前面试被问到,如何不改变字符串内存地址,修改它的内容。没答上来,最后问了面试官如何实现,答曰:反射。

 

正好看到一篇文章:

https://blog.youkuaiyun.com/a925907195/article/details/46975171
自己也记录一下

 

        String str01 = "aaa";
        String str02 = "aaa";
        String str03 = "bbbb";
        System.out.println(str01.hashCode() + "/" + str02.hashCode() + "/" + str03.hashCode());
        Field field = str02.getClass().getDeclaredField("value");
        field.setAccessible(true);
        field.set(str02, new char[]{'b', 'b', 'b', 'b'});
        System.out.println(str01 + "/" + str02);
 /* jdk7以后已不包含 private final int count;
   field = str02.getClass().getDeclaredField("count");
        field.setAccessible(true);
        field.set(str02, 4);*/

        System.out.println(str01 + "/" + str02);
        System.out.println(str01.hashCode() + "/" + str02.hashCode() + "/" + str03.hashCode());
        field = str02.getClass().getDeclaredField("hash");
        field.setAccessible(true);
        field.set(str02, 0);
        System.out.println(str01.hashCode() + "/" + str02.hashCode() + "/" + str03.hashCode());
        System.out.println(str01 == str02);
        System.out.println(str02 == str03);

运行结果

 

96321/96321/3016832
bbbb/bbbb
bbbb/bbbb
96321/96321/3016832
3016832/3016832/3016832
true
false

 

 

  1. 根据Java String的特性,str01和str02指向同一个内存地址,所以str01,str02始终保持一致。
  2. String不能修改的本质是一个final的字符数组(private final char value[];),但是final只在编译时有效,而运行期间是没有作用的,所以可以通过反射修改数组的值。
  3. 代码中修改后字符串的hashcode之所以没有变化,是因为String对象会缓存hashcode,去掉缓存就可以看到变化。
  4. 根据Java String的特性,上面代码创建的所有字符串对象都保存在String Pool中,代码中str02与str03的内容相同,地址却不同,所以String Pool中就存在两个相同的字符串。

 

至于 hashcode 为什么没有改我们看源码也很清楚 

 

    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

 

 

 

java为了提高效率, 只再第一次调用hashcode函数时生成一次hash, 并把值存在这个实例里面。 以后即使value数组的值变化了,也不再生成新的hash。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

dingsai88

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

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

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

打赏作者

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

抵扣说明:

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

余额充值