Java反射------>修改Sting底层数组

public static void main(String... args){
    String a ="abc";
    System.out.println(a);
}
//这段代码执行以后输出结果是
//abc
//那我们能不能有个方法改变a的值的同时不改变a的地址?
//有些聪明的小伙伴就说了 可以啊 我们这样 a = "abcd";
//这个方法可行,但是有一个问题就是他把a的地址给改变了,这是不符合题意的
//我们可以测试一下
public static void main(String... args)  {
        String a = "abc";
        System.out.println(a);
        System.out.println(System.identityHashCode(a));
        a="abcd";
        System.out.println(a);
        System.out.println(System.identityHashCode(a));
}
//此时输出结果为:
//        abc
//        1956725890
//        abcd
//        356573597
//这表示a的地址被改变了
//System.identityHashCode(a) 这个方法是用来返回对象在内存中的地址 
//不管其是否有重写hashCode方法
//那么我们有没有什么方法可以来改变a的值但不改变其地址呢?
//答案肯定是有的,在此之前我们先看个东西
public static void main(String... args) {
        char[] a ={'a'};
        System.out.println(a[0]);
        System.out.println(System.identityHashCode(a));
        a[0]='b';
        System.out.println(a[0]);
        System.out.println(System.identityHashCode(a));
}
//这段代码输出结果为:
//        a
//        1956725890
//        b
//        1956725890
//这里我们可以看见我们修改了a数组中的值,但是a数组的地址却没有发生改变
//我们都知道String类的底层是一个char数组,这表示我们如果修改String的底层数组中的值,
//是不是就可以使String的值改变,而不改变其地址
//但是我们都知道String的不可变特性是因为其底层的数组是有private final 
//修饰的一个char类型的数组
//fina修饰引用类型的属性我们知道这是表示其地址不可改变,但是值却可以改变
//如这段代码:
static final char[] a ={'a'};
public static void main(String... args) {
      System.out.println(a[0]);
      a[0]='b';
      System.out.println(a[0]);
}
//其输出结果为:
//a
//b
//那既然final修饰的引用类型地址不可改变,但值可以改变,为啥String却说是不可变呢?
//这就是因为这个方法由private这个权限修饰符所造成的
//private这个方法我们都知道 这个表示私人的即由其修饰的属性或方法只能在类的内部调用,
//外部访问不到,这就是String的不可变特性
//好了,说了那么多,我知道大家想知道如何来修改String的值而不改变其地址吧
//这里就要用到Java中的一个特性--->反射
//它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。
//反射机制所需的类主要有java.lang包中的Class类和java.lang.reflect包中的
//Constructor类、Field类、Method类和Parameter类。
//我们今天就用java.lang包中的Class类来修改String中的value数组
    public static void main(String... args) {
        String a = "abc";
        System.out.println(a);
        System.out.println(System.identityHashCode(a));
        //我们调用Object类中的getClass方法来获取a的Class类;
        //注意Class类没有new Class()方法
        Class c = a.getClass();
        try {
            //我们调用Class类中的getDeclaredField()方法
            //来获取String类中的不可变数组value
            Field field = c.getDeclaredField("value");
            //将该对象的可访问标志设置为指定的布尔值。
            //值true表示反射对象在使用时应该禁止Java语言访问检查。
            //值为false表示反射对象应该强制Java语言访问检查。
            field.setAccessible(true);
            //形参:
            //obj – 需要修改其字段的对象
            //value – 正在修改的obj字段的新值
            //因为value是一个数组所以使用String中的toCharArray()
            //方法使String对象转换为char数组
            field.set(a, "abcd".toCharArray());
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(a);
        System.out.println(System.identityHashCode(a));
    }
//此时输出结果为:
//	abc
//	1956725890
//	abcd
//	1956725890
//此时我们的任务就完成了,修改a的值,但不改变a的地址

本文系作者 @ 原创发布在 IT梦。未经许可,禁止转载。

喜欢()
0 0 投票数
Article Rating
订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论
热门搜索
1 文章
0 评论
0 喜欢
Top
0
希望看到您的想法,请您发表评论x
()
x