Java.lang.String类可能是每个人最常用的类别,但是您真的了解它是如何实现的吗?仔细阅读本文,您可以一目了然地理解。
从源代码可以看出,字符串是由最终声明的常数类,该类别不能由任何类别继承,并且一旦创建了字符串对象,此对象中包含的字符序列才能修改方法,直到对象对象被摧毁。这就是我们需要特别注意的(此类的某些方法似乎改变了字符串。事实将引入)。它还实现了可比较的接口,以比较两个字符串的大小(单个字符的ASCII代码),该界面将在特定方法之后实现;最终意识到实现; CharSequare接口表明它是有序字符的集合,相应的方法将在稍后引入。
字符串字符串实际上是一个char数组。
字符串类有许多结构。您可以通过初始化字符串,字符数组或字节数组等创建字符串对象。
字符串类重写了等值方法。将其与构成字符串的每个字符是否相同。如果相同,则返回true,否则将返回错误。
字符串类的HashCode算法非常简单,主要在中间进行循环。计算公式如下:
s [0] 31^(n-) + s [1] 31^(n-2) + ... + S [n-1]
s数组是源代码中的val数组,即构成字符串的字符阵列。这里有数字31。为什么选择31作为产品因素,并且不使用常数声明?有两个主要原因:
1,31是大量质量数字,是哈希码的首选质量数字之一。
2,31可以通过JVM优化,31 * i =(i?5)-i。由于位移操作比乘法更快,性能更快。
我们知道字符串由字符数组组成。此方法是通过索引(数组集)返回带有指定索引的单个字符。
这是一种本地方法:
公共本地字符串intern();
当调用实施方法时,如果字符串确定的字符串已经在池中,则将返回字符串。否则,将此字符串对象添加到池中并返回此对象的引用。
这句话是什么意思?也就是说,调用字符串对象,如果在常数池中有此对象,请直接返回对字符串的引用(返回堆的存在中的堆,池将是返回游泳池);如果不是,则该对象将是此对象。添加到池并返回池中的参考。
关于字符串类中的许多方法,我不会一个一个介绍它们。让我们看一下。字符串类未转换。
分析一个经典的访谈问题:
答案是:真实,正确,错误,真实
对于上述主题,我们可以首先查看图片,如下所示:
首先,字符串A =“ ABC”将进入常量池以检查是否存在“ ABC”。发现没有,因此在常数池中创建“ ABC”对象,并将常数池中的引用分配给a;第二个字面卷字符串b =“ abc”,该字符串b =“ abc”,它检测到常数池中的对象,并直接分配给B;第三是由新关键字创建的对象。您不需要在常数池中创建,然后在堆中创建对象,将堆中对象的参考值分配给C,然后指向对象到恒定池。
应该解释的是,在对象中,equals()用于比较内存地址,但是字符串重写了equals()方法以比较内容。
注意:查看上图中的红色箭头,新关键字创建的字符串对象,如果存在常数池,则在桩中创建的对象将指向常数池的引用。
让我们再次查看一个问题,以创建包含变量表达式的对象:
由于str3包含可变str1,因此无法确定编译器是恒定的,并且将在桩区域中创建一个字符串对象。STR4是两个常数添加,并且可以直接引用常数池中的对象。
字符串类是Java中不变的类。
简而言之,不可用的类别是,创建后不能修改实例。
字符串的不变话题应该是古老的。自母亲出生以来,弦乐与他们的兄弟姐妹不同。
因此,字节,int,短,长,长和其他基本类型的基本类型都不会使其播放。
如果您仔细阅读源代码,您会发现这样的句子:
粗略的含义是弦是一个常数,注定要从出生开始不变。
首先,您需要补充一个易于混淆的知识点:使用最终修改基本类型变量时,您不能重新启动基本类型变量的值,因此无法更改基本类型变量。类型变量,仅保留参考。最终仅保证此参考变量引用的地址不会更改,也就是说,始终引用相同的对象,但是可以完全更改此对象。例如,如果数组引用了手指,则必须将其定向到初始化时的数组,但是可以更改此数组的内容。
字符串类在最终关键字中进行了修改,因此我们认为它是一个不变的对象。但是真的不可变吗?
每个字符串由许多单个字符组成。我们知道其源代码由字符数组组成。
值通过最终修改,它只能确保参考不会更改,但是按值指向的堆中的数组是真实数据。只要可以操作堆中的数组,数据仍然可以更改。值是基本类型,那么它必须是可变的。即使被宣布为私人,我们也可以通过反思更改它。
通过在之前和之后的两次打印的结果,我们可以看到str值已更改,但是str的内存地址没有更改。我们会认为字符串类型是不变的。
首先,我们应该从设计师的角度考虑问题,不是说这不好,这是不合理的:
有兴趣的朋友还可以读取String的源代码,即强大的3000+。
当字符串是新的时,有必要创建一个对象。+缝合数是相同的。尽量不要在程序中使用 +剪接。建议使用StringBuffer或StringBuilder。