String源码分析之为什么Java语言中的String不能改变?
小标 2018-11-26 来源 : 阅读 1358 评论 0

摘要:本文主要向大家介绍了String源码分析之为什么Java语言中的String不能改变?通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了String源码分析之为什么Java语言中的String不能改变?通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。


什么是不可变对象:


大家都知道java中String对象是不可变的,现在明确一个概念什么叫不可变对象。


一个对象在创建成功之后,对象中的成员变量不可被改变,基本类型的成员值不可改变,引用类型的成员变量不能指向不可改变


区分Java中对象和对象引用


下面用String来举例说明


String a = "abc"

 

System.out.println(a)

 

a = "abcABC"

   


因为a 只是指向String类型变量的一个引用,上面的代码只是将变量a由指向"abc"这个String对象转向"abcABC"这个对象


内存结构图如下:



Java和C++的一个不同点是, 在Java中不可能直接操作对象本身,所有的对象都由一个引用指向,必须通过这个引用才能访问对象本身,包括获取成员变量的值,改变对象的成员变量,调用对象的方法等。而在C++中存在引用,对象和指针三个东西,这三个东西都可以访问对象。其实,Java中的引用和C++中的指针在概念上是相似的,他们都是存放的对象在内存中的地址值,只是在Java中,引用丧失了部分灵活性,比如Java中的引用不能像C++中的指针那样进行加减运算。


为什么Java中的String是不可变的


我们从两个方面来看,源码的设计和这样设计的优点


1:源码分析



上面是JDK8的String成员对象,字符数组,int类型的hash值,long类型的serialVersionUID都是provate类型的,并且没有提供get set方法,并且value[] 和 serialVersionUID是final类型的,对于外界这些字段的值都是没发改变的。在Java中数组也是对象,所以上图中的value是指向字符数组的一个引用。


在执行完 String s = "abc"后内存布局应该是这样的



进一步验证String对象是不可变的


public String substring(int beginIndex, int endIndex) {

        if (beginIndex < 0) {

            throw new StringIndexOutOfBoundsException(beginIndex);

        }

        if (endIndex > value.length) {

            throw new StringIndexOutOfBoundsException(endIndex);

        }

        int subLen = endIndex - beginIndex;

        if (subLen < 0) {

            throw new StringIndexOutOfBoundsException(subLen);

        }

        return ((beginIndex == 0) && (endIndex == value.length))  this

                : new String(value, beginIndex, subLen);

    }

   


上面是String中的subString方法


注意到最后标红的subString返回的新被截取的字符串都是新new出来的,


String s = "abc"

s = s.subString(0,1)

   


也就是上面代码中"abc"字符串对象并没有被改变,subString方法返回的是一个新的String对象然后让s指向该新对象,大家可以去验证,String类中其他类似的改变字符串的方法都是返回一个新的对象


2:设计String类为不可变的优点


1)出于安全考虑举例说明



HashSeths=newHashSet();


StringBuildersb1=newStringBuilder("aaa");


StringBuildersb2=newStringBuilder("aaabbb");


hs.add(sb1);


hs.add(sb2);//这时候HashSet里是{"aaa","aaabbb"}


StringBuildersb3=sb1;


sb3.append("bbb");//这时候HashSet里是{"aaabbb","aaabbb"}


System.out.println(hs);


         

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注编程语言JAVA频道!


本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved