栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

==和equals

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

==和equals

equals在obejct这个原始的类中,是直接比较的两个对象引用 引用的地址值(即对象的地址)。

  • object中的equals
public boolean equals(Object obj) {
    return (this == obj);
}

其它继承了object的类,一般都会重写equals方法,

例如string ,它的实现具体为:

  • 先比较两对象的地址值

  • 后比较其字符数组内容。

  • string 的equals实现。

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}
String sw =new String("232");
String s2 =new String("232");
String s3=s2;

//true
System.out.println(s3==s2);

//false
System.out.println(sw==s2);//对象引用 的等号运算 其实比较的是地址值。

//true
System.out.println(sw.hashCode()==s2.hashCode());//hashcode 可以重写 ,string类型的hashcode 一开始默认为0,之后会重新计算后保存(E(i:0->n) value[i]*31^(n-1) );

//false
System.out.println(sw.equals(s2));//这里字符串重写了equals。(1.8版本 : string类型的equals 是先比较 对象引用引用的地址,之后再比较两者的每个字符);

hashcode 在object中 的实现是使用了本地方法,将对象的地址转化为一个整数(注意 这里 返回的hashcode并不等于 对象的地址 )

而string类型的实现的hashcode 其实是 通过 迭代计算 字符数组的每一个字符 求出的一个和(运算过程中有可能发生整数溢出)。

开始创建一个string对象时,它的hash为0,当第一次调用hashcode后,之后返回的便是其第一次调用的结果的缓存。

  • string 实现的hashcode

    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;
    
            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }
    

那么既然hashcode 是通过计算字符串对象中的字符数组获得的结果,那么相同内容的字符串对象不就直接使用hashcode就可以了吗?何必遍历字符数组一一对比每一个字符呢?

理由大致有两个:

  • 上面讲到string类型的hashcode计算时可以会发生数值溢出,那么,这样一来可能两个不同内容的字符串对象就会得到相同的hash值

  • 另外 虽然字符数组是用final修饰的,但是里面的字符是可以修改的,所以可能通过篡改其中的字符,但是之前调用了hashcode,并将其返回的hash值保存了起来,导致

    hash相等,却实际内容不相等。

 //测试当通过反射修改了原来字符串对象中的字符数组的内容。

Class  stringClass=(String.class);

 Constructor constructor =stringClass.getConstructor(String.class);

 String string=(String) constructor.newInstance(sw);
 //true
 System.out.println(string.hashCode()==sw.hashCode());



 Field field = stringClass.getDeclaredField("value");

 //设置私有属性可以访问
 field.setAccessible(true);

 char[] arr= (char[])field.get(string);

 //修改其中的内容
 arr[0]='+';

 field.set(string,arr);
 
 //true
 //虽然修改了其中的字符,但是由于之前的hashcode已经算出来了,所以就是用了之前的hashcode值
 //这在比较字符串中是不安全的,所以equals没有直接使用hashcode作为相等的依据
 System.out.println(string.hashCode() ==sw.hashCode());
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/315533.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号