• 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html
  • 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html

通过反射改变String类的值

技术杂谈 勤劳的小蚂蚁 3个月前 (01-20) 79次浏览 已收录 0个评论 扫描二维码

通常认为String类对象是不可修改的,例如:

String s=“abc”;
s=“123”;
System.out.println(s);
首先创建一个String对象s,然后让s的值为“abc”, 然后又让s的值为“123”。 从打印结果可以看出,s的值确实改变了。
这里的s只是一个String对象的引用,并不是对象本身。
对象在内存中是一块内存区,成员变量越多,这块内存区占的空间越大。引用只是一个4字节的数据,里面存放了它所指向的对象的地址,通过这个地址可以访问对象。 也就是说,s只是一个引用,它指向了一个具体的对象,当s=“123”; 这句代码执行过之后,又创建了一个新的对象“123”, 而引用s重新指向了这个新的对象,原来的对象“abc”还在内存中存在,并没有改变。
String 类的成员对象有
privatefinalchar[] value;
privatefinalint offset;
privatefinalint count;
value,offset和count这三个变量都是private的,并且没有提供setValue, setOffset和setCount等公共方法来修改这些值,所以在String类的外部无法修改String。也就是说一旦初始化就不能修改, 并且在String类的外部不能访问这三个成员。此外,value,offset和count这三个变量都是final的, 也就是说在String类内部,一旦这三个值初始化了, 也不能被改变。
所以可以认为String对象是不可变的了。
但,可以通过反射改变String value的值
   String s = “abcd”;       

   System.out.println(“s = “ + s); 

   Field valueField = String.class.getDeclaredField(“value”);     

   valueField.setAccessible(true);      

   char[] value = (char[]) valueField.get(s);       

   value[3] = ‘e’;      
   System.out.println(“s = “ + s);  

   valueField.set(s, new char[]{‘1’‘2’‘3’});       

   Field countField = String.class.getDeclaredField(“count”);
   countField.setAccessible(true);
   countField.set(s, 3);
   System.out.println(“s = “ + s);

特别注意

通过发射修改String的值的时候,特别要注意维护好count的值,因为修改后的字符串长度可能已经改变。看String源码,length方法就是返回count的值。如下:
public int length() {
   return this.count;
}


    丨极客文库, 版权所有丨如未注明 , 均为原创丨
    本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
    转载请注明原文链接:通过反射改变String类的值
    喜欢 (0)
    [247507792@qq.com]
    分享 (0)
    勤劳的小蚂蚁
    关于作者:
    温馨提示:本文来源于网络,转载文章皆标明了出处,如果您发现侵权文章,请及时向站长反馈删除。

    您必须 登录 才能发表评论!

    • 精品技术教程
    • 编程资源分享
    • 问答交流社区
    • 极客文库知识库

    客服QQ


    QQ:2248886839


    工作时间:09:00-23:00