zoukankan      html  css  js  c++  java
  • 如何改变String类的值,保证地址不变!

    一、String是一个不可变类

      我们都知道String是一个不可变类,因为它的源码内部维护着一个final修饰的char数组,final修饰的变量不可以被改变,修饰的方法不可以被重写,修饰的类不可以被继承:(简要源码)

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

    也就是说:String对象一旦创建,就不可改变。拼接、截取或者重新赋值都是在重新建对象。

    做一下代码演示:

    /**
     * @Author 程Sir
     * @Version 2020年3月26日上午11:20:51
     * @description 描述:字符串不可以被改变
     */
    public class Demo {
    
        public static void main(String[] args) throws IOException {
            String str = "不变的字符串";
            System.out.println("1. " + str +" : " + str.hashCode());
            
            str = str.substring(2);
            System.out.println("3. " + str +" : " + str.hashCode());
            
            str = str+1;
            System.out.println("2. " + str +" : " + str.hashCode());
        }
    
    }

    输出的结果是:

      1. 不变的字符串 : 83361354
      3. 的字符串 : 927327327
      2. 的字符串1 : -1317623886

    通过演示表明:hashcode值每次都是不一样的。说明操作的不是同一对象,再次过程中有新的对象被创建。

    二、应用Java中的反射机制

      我们学习了反射机制,了解到:反射是在运行期能够对类的属性、方法进行操作。即:运行期绑定。那么我们是不是可以在String运行期对它的值进行一个完美操作了,答案是肯定的,完全可以的,看以下代码:

    /**
     * @Author 程Sir
     * @Version 2020年3月26日上午11:20:51
     * @description 描述:字符串不可以被改变
     */
    public class Demo {
    
        public static void main(String[] args) throws IOException {
            String str = "不变的字符串";
            System.out.println("1. " + str +" : " + str.hashCode());
            
            try {
                //反射通过属性拿到值,Sting类的属性char数组的属性名为:value
                Field field = str.getClass().getDeclaredField("value");
                //设置该属性为可操作
                field.setAccessible(true);
                //改变该属性的值:改变char数组
                field.set(str, new char[]{'程','s','i','r'});
                
                System.out.println("2. " + str+" : " + str.hashCode());
                                            
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
    输出的结果是:

      1. 不变的字符串 : 83361354
      2. 程sir : 83361354

    从演示结果中,我们发现,字符串str的hashcode值两次相等,并没有发生改变,说明是同一对象,但前后的值(内容)完全是发生了改变。即达到了我们的目的:String类的值是可以通过Java的反射机制进行改变的。

    三、总结

      最后,我们做一个总结:

      String类是用final关键字修饰的,那值就是不可以改变,值不可以改变,导向到结果是这个值的引用地址在内存中是不可被改变。再String类的本质是内部维护这一个char类型的数组,明确这点后,我们既可以通过Java反射机制的特性,在运行期对其内部的char数组内容进行操作,从而达到改变String类内容的目的。

  • 相关阅读:
    青春小女生 科研大梦想——微软亚洲研究院女实习生的故事
    刷新神经网络新深度:ImageNet计算机视觉挑战赛微软中国研究员夺冠
    优质博士的养成之道——对话2015微软学者奖学金获得者
    洪小文谈科研:自信与谦虚并行
    Java 8 新特性
    Java 实例
    Java 文档注释
    Java Applet 基础
    Java 多线程编程
    Java 发送邮件
  • 原文地址:https://www.cnblogs.com/chenglaoshi/p/12573184.html
Copyright © 2011-2022 走看看