String常用特性分析

一、equals

对象之间的比较用==,比较的是两个对象的引用,对象通过引用才能到Java堆里面找到对应的对象实例。

基本类型(byte、short、int、long、double、float、boolean、char,String不是基本类型)

而两个字符串(非直接或间接通过new关键字创建)相同的数据使用==进行比较,能够得到false的原因是:位于Java堆中的字符串常量池会在类加载的时候初始化,所有通过直接赋值的字符串都会在准备阶段之后在堆中生成字符串对象实例,并将该字符串对象实例的引用值存到字符串常量池中。字符串常量池中存放的是引用值,引用对应的具体对象实例是在堆中开辟的另一块内存空间存放的。

在String的equals实现中,首先,会使用==进行引用的比较。

然后通过instanceof确认参数的对象类型是不是字符串对象类型。

确认参数的对象类型是字符串类型之后,通过while循环遍历比较这两个字符串对象的字符数组中的每一个字符的值是否相同,而char是字符也是基本类型,基本类型通过==比较的是字符值。

对于其他自建对象来说,我们也可以实现equals方法来达到比较两个类型相同而引用指向不同实例的实例对象的内容比较。可参考Integer中equals的实现。

通过下面的结果也可以知道,equals比较的是值。

==比较的是对象的引用,如果两个对象引用指向的是同一个对象,则返回true;

在String中equals比较的是值,比较的是字符串中的每一个字符包括顺序是否完全相同。

为什么说String中呢?因为String中的equals是重写的Object的equals方法。而Object中equals其实比较的就是两个对象的引用。

同样的Integer、Long等基本类型对应的包装对象中比较的也是值。

在使用Integer等包装对象类型时,需要注意它们各自在常量池中的实现。

如:Integer在常量池中的实现其中一个特征是,Integer在常量池的存储范围是[-128, 127]。

由于127在范围内,因此a和b指向的是常量池中的对象;而128不在范围内,因此m和n都是在堆内存中创建一个新的对象来保存这个值,并把引用值分别赋给m和n,所以m和n指向的并不是同一对象。

二、hashCode

默认hash为0

当hash为0,或者字符数组长度不为0时,通过h = 31 * h + val[i]; 计算最终的hash

 当对其中一处打断点时,运行程序后,不仅JDK中所有要加载的字符串数据,都会重新计算hashCode。算法一致,所以同一字符串每次得到的hash值都相同。

而由于“通”的ASCII码为36890,“话”的ASCII码为35805,通过hash计算得hash = 31*(31*0 + 36890)+ 35805 = 1143590 + 35805 = 1179395

“重”的ASCII码为37325,“地”的ASCII码为22320,通过hash计算得hash = 31 * (31*0 + 37325) + 22320 = 1157075 + 22320 = 1179395

可以得出hash值相同,不等同于内容也相同。字符串哈希算法无法保证两个不同的字符串能一定得到不同的哈希值。

 

 

感谢以下博客博文对本文的帮助。

https://blog.csdn.net/lcsy000/article/details/82782864

原文地址:https://www.cnblogs.com/feiyang930112/p/11299275.html