首页>>后端>>java->扒开外衣仔细分析:String为什么不可变

扒开外衣仔细分析:String为什么不可变

时间:2023-11-30 本站 点击:0

前言

说到Java源码,我相信小伙伴们或多或少都有接触,比如util包中常见的ArrayList、HashMap、LinkedHashMap,还有前面我们学过的多线程相关类,如:ExecutorsCountDownLatchCyclicBarrier,又或者是lang包中的ObjectIntegerStringThread等。

这些都是我们比较常见的类,不过对于他们的实现原理,我们有时候并不能说出个所以然来,甚至有些人写了四五年代码,连最最常见的String如何实现都没有看过,还总是抱怨每天总是搬砖、前途迷茫。说实话,学习源码并不仅仅是为了应对面试,更重要的是我们通过阅读源码的过程,学习它的设计思想,这种思想在我们项目中完全可以实践出来。

总结来说,阅读源码有以下几点好处:

学习优秀的设计思想;

增加面试实力,横扫一片;

代码日常评审时大秀肌肉。

String源码分析

String在日常开发中的使用频率相当高,所以今天就要扒开String的外衣,看看它究竟为什么这么受欢迎。

2.1 不可变性

publicfinalclassStringimplementsjava.io.Serializable,Comparable<String>,CharSequence{...}

从代码中可以看到,String类由final关键字修饰,这也意为着String类不可被继承,创建后不能被修改。

String类同时实现了三个接口:

Serializable:实现序列化,标记接口,用于标识序列化,未实现该接口无法被序列化。

Comparable:对两个实例化对象比较大小

CharSequence:String本质是个char数组,该接口为只读的字符序列。

2.2 成员变量

/**Thevalueisusedforcharacterstorage.*/privatefinalcharvalue[];/**Cachethehashcodeforthestring*/privateinthash;//Defaultto0/**useserialVersionUIDfromJDK1.0.2forinteroperability*/privatestaticfinallongserialVersionUID=-6849794470754667710L;/***ClassStringisspecialcasedwithintheSerializationStreamProtocol.*/privatestaticfinalObjectStreamField[]serialPersistentFields=newObjectStreamField[0];

String 中保存数据的是一个 char 的数组 value, value 同样也是被 final 修饰,这就意外着该数组无法被修改,同时value 的访问权限是 private ,外部访问不到该变量,String 也没有提供 value 的相关操作方法,所以 value 一旦生成就无法再被被修改。

2.3 常见方法

接下来看String类中几个常见的方法是如何实现的

equals

publicbooleanequals(ObjectanObject){//内存地址是否相同if(this==anObject){returntrue;}//目标对象是否为String类,不是的话直接返回falseif(anObjectinstanceofString){StringanotherString=(String)anObject;intn=value.length;//判断两者长度是否相等if(n==anotherString.value.length){charv1[]=value;charv2[]=anotherString.value;inti=0;//比较两者中每一个字符是否相等while(n--!=0){if(v1[i]!=v2[i])returnfalse;i++;}returntrue;}}returnfalse;}

截取字符串:substring

publicStringsubstring(intbeginIndex,intendIndex){if(beginIndex<0){thrownewStringIndexOutOfBoundsException(beginIndex);}if(endIndex>value.length){thrownewStringIndexOutOfBoundsException(endIndex);}intsubLen=endIndex-beginIndex;if(subLen<0){thrownewStringIndexOutOfBoundsException(subLen);}return((beginIndex==0)&&(endIndex==value.length))?this:newString(value,beginIndex,subLen);}

总结

通过源码可以看到,对于满足条件的起始/终止下标,该方法会调用new String()构成器,而该构造器最终通过System.arraycopy生成一个新的字符串返回,这也就意为着该方法并不会在原有字符串基础上进行修改。

同样的,我们可以查看replaceconcat等方法源码,他们都会不会修改原有字符串,而是会生成一个新的字符串对象返回,这也是String不可变的表现。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/java/4939.html