• 半夜思考,为什么 String 具有不变性


    学习 Java 的数据类型时,特殊关照了 String 类型,具有不变性。

    当时没有深入思考为什么 String 有不变性。而且我只碰到了 String 才有不变性。Java这样设计的缘由何在。

          突然在想,为什么 Struts2 中的 action 的返回值为什么也是 String 类型的,不是其他类型,SpringMVC中 handle 也是返回的是 String 类型【ModelAndView 里面也包含了视图名的字符串形式,void就不提了,处理 AJAX 】。

        

          下面就好好分析这个字符串不变性。

    所谓不变性就是一旦创建一个字符串对象,这个字符串对象的内容就不会被改变了。比如:

    package com.msym.test;
    
    public class Test {
        public void show() {
            String str1 = "aaa";
            String str2 = "aaa";
            String str3 = new String("aaa");
            System.out.println("str1的hashCode: " + str1.hashCode());
            System.out.println("str2的hashCode: " + str2.hashCode());
            System.out.println("str3的hashCode: " + str3.hashCode());
            
            str1 = "aaa" + "b";
            System.out.println("str1的hashCode: " + str1.hashCode());
            System.out.println("str2的hashCode: " + str2.hashCode());
        }
        @org.junit.Test
        public void test(){
            show();
        }
    }

    image

    打印出来的结果说明,str1,str2,str3是指向同一块内存空间的,当修改了 str1时,就创建了一个新的字符串了。

    上面创建 str1,str2,str3:

            创建 str1 时,常量池里面肯定是没有常量“aaa”,所以会创建出一个,但是当创建 str2时,因为之前已经创建过  “aaa”了,所以会直接指向这个“aaa”;创建 str3 时,尽管使用了 new 关键字,但是还是会先去常量池去搜寻“aaa”,如果存在,就只在堆内存中开辟一段空间,用以存放常量池中“aaa”的地址,如果不存在,那么就先在常量池中创建“aaa”,然后在堆中开辟空间,存储常量池中“aaa”的地址。

    下面画张图来说明:【其中的 0X1122 是常量池中“aaa”的地址头,】

    image

          而且 String 类的任何方法都不是去修改字符串的值,而是创建了一个新的字符串,原来的字符串如果没有被引用的话,会在一段时间内被 gc 掉,这样貌似看来,这个不变性并没有带来什么好处,反倒浪费了不少内存,但是这样的机制正好有了安全性,只要创建出一个 String 对象,只要他没有被 gc ,任何方法来读取这个对象都会是同一个,不会出现两个一样的,这也是为什么 String 类型在网络连接,数据传递,以及各大框架使用的这么频繁。

    当然,如果只是想使用 String类的功能,有更好的选择,那就是线程安全的 StringBuffer和线程不安全的StringBuilder。

    1

  • 相关阅读:
    [nodejs] web后端开发时, 用hapi/Joi对前端提交的数据进行校验--随笔
    [C++]类的空指针调用成员函数后,会发生什么事?
    赵家庙保险队大队长【永远置顶】
    NX二次开发-NXOpen C# OpenFileDialog弹出选择文件对话框
    NX二次开发-NXOpen C# string转tag
    NX二次开发-UFUN创建扫掠UF_MODL_create_sweep
    NX二次开发-NXOPEN C# WinForm点构造器UF.Ui.PointConstruct和UI加锁解锁UF.Ui.LockUgAccess
    vue 移动端手写手机验证码登录
    java--Scanner扫描器
    react中this.props.history实现跳转页面的使用方法
  • 原文地址:https://www.cnblogs.com/daimajun/p/7221562.html
Copyright © 2020-2023  润新知