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类内容的目的。

  • 相关阅读:
    小数在计算机中的存储形式
    pyenv、virtualenv、virtualenvwrapper三种python多版本介绍
    【转】【WPF】WPF中MeasureOverride ArrangeOverride 的理解
    【转】Visual Studio团队资源管理器 Git 源码管理工具简单入门
    C#客户端(WinForm)开机自动启动实现
    C# 使用XPath解析网页
    【C#】使用DWM实现无边框窗体阴影或全透窗体
    【转】【Centos】centos 安装libtorrent/rtorrent
    【Centos】【Python3】yum install 报错
    【Python】Centos + gunicorn+flask 报错ImportError: No module named request
  • 原文地址:https://www.cnblogs.com/chenglaoshi/p/12573184.html
Copyright © 2011-2022 走看看