利用反射机制改变String的值

来源:互联网 发布:python 正则匹配 开始 编辑:程序博客网 时间:2024/05/22 23:19

前言

在很多的面试中会被问到有关String和StringBuffer的区别,简单来说就是:

一个变量和常量的关系。
StringBuffer对象的内容可以修改;
而String对象一旦产生后就不可以被修改,重新赋值其实是两个对象。

学过了反射机制,知道了其是非常强大的,那么String指向的地址的值真的不能改变吗?
答案是否定的!

为什么说String的值是不可改变的?

看如下的代码:

package com;/** * @author 张俊强~ * @time 2017/06/18 * @function 打印String的值 * */public class ReflectApply1 {    public static void main(String[] args) {        // TODO Auto-generated method stub        String str="str1";        System.out.println(str.hashCode());        str="str2";        System.out.println(str.hashCode());    }}

我们来看一下输出的结果:

35410243541025

可知这个str在重新赋值后,它指向的地址其实是已经发生改变了的!

我们来看一下String类的源码:

public final class String    implements java.io.Serializable, Comparable<String>, CharSequence {    /** The value is used for character storage. */        private final char value[];        //后面省略    }

可知String是一个被final修饰的字符数组,所以String的值确实是不可改变的!

利用反射机制来改变String的值

首先我们看源码知道String类有属性char value[],我们可以利用反射机制获取这个属性,然后改变其值不就可以改变String的值了吗?
代码如下:

package com;import java.lang.reflect.Field;/** * @author 张俊强~ * @time 2017/06/18 * @function 改变String的值 */public class ReflectApply1 {    public static void main(String[] args) throws Exception {        // TODO Auto-generated method stub        String str = "不可变的字符串";        System.out.println(str.hashCode()+":"+str);         //改变前的hash值        Field f = str.getClass().getDeclaredField("value"); //获取value属性        f.setAccessible(true);                              //设置其可以被访问(private)        f.set(str, new char[] { '改', '变', '后', '的', '值' }); //改变其值        System.out.println(str.hashCode()+":"+str);         //改变后的hash值    }}

输出结果:

-459725323:不可变的字符串-459725323:改变后的值

可知对应的在修改了String的值后其相应的hash值未发生改变。

后记

为什么String类型要设置成fianl类型的呢?其实原因有很多,主要原因是String类型在Java中使用的次数是非常频繁的,如果每次改变都需要重新销毁再赋值的话,就会大量调用GC,设置成fianl也是为了减少GC的次数嘛(GC是非常耗时的)。
具体可以看看知乎的回答:https://www.zhihu.com/question/31345592

阅读全文
0 0