Java从入门到放弃(三)equals和==

1、equals和==的区别

    除了基本类型,equals和==比较的都是对象的地址值。如下为Object的equals方法

public boolean equals(Object obj) {
        return (this == obj);
    }

    对于基本数据类型,equals和==比较的都是值,数值相等就相等。

    基本数据的包装类型, 包装类都重写了equals方法,如下为Integer的equals方法。

public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }
    所以包装类型的equals比较的是对象的值,如果值相等,equals就返回true。

    ==比较的时候:除了Float和Double,都有对应的缓存

包装类型缓存对象
Booleantrue,false
Character0-127
Byte-128-127
Short-128-127
Integer-128-127
Long-128-127
Float无缓存值
Double无缓存值


  对于所有包装类型,==在缓存对象范围内,如果数值相等==返回true,缓存范围之外==返回false

String类  对于String,重写了equals方法,比较的是字符串的值。

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String aString = (String)anObject;
            if (coder() == aString.coder()) {
                return isLatin1() ? StringLatin1.equals(value, aString.value)
                                  : StringUTF16.equals(value, aString.value);
            }
        }
        return false;
    }

==比较,因为常量池的存在,有时候会在常量池共用对象的引用,具体参考Java从入门到放弃(一)String类

其他引用类型  如果重写了equals方法,则按照重写的规则进行对比如果没有重写,则依据其父类的equals方法,如果一个类没有继承任何类,则默认基础Object类,所以equals和==一样比较的是地址值。

public class ClassA {
    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class ClassB {
    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof ClassB)) return false;
        ClassB classB = (ClassB) o;
        return age == classB.age &&
                Objects.equals(name, classB.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(age, name);
    }
}
public class Main {
    public static void main(String[] args) {
        ClassB classB1 = new ClassB();
        ClassB classB2 = new ClassB();
        ClassA classA1 = new ClassA();
        ClassA classA2 = new ClassA();
        System.out.println(classB1.equals(classB2));   //true
        System.out.println(classA1.equals(classA2));   //false
    }
}

2、equals和hacode

    equals方法:JDK中说明了实现equals()方法应该遵守的约定:

    (1)自反性:x.equals(x)必须返回true。

    (2)对称性:x.equals(y)与y.equals(x)的返回值必须相等。

    (3)传递性:x.equals(y)为true,y.equals(z)也为true,那么x.equals(z)必须为true。

    (4)一致性:如果对象x和y在equals()中使用的信息都没有改变,那么x.equals(y)值始终不变。

    (5)非null:x不是null,y为null,则x.equals(y)必须为false

   hashcoed方法:

public native int hashCode();

可以看出,hashCode()是一个native方法,而且返回值类型是整形;实际上,该native方法将对象在内存中的地址作为哈希码返回,可以保证不同对象的返回值不同。

与equals()方法类似,hashCode()方法可以被重写。JDK中对hashCode()方法的作用,以及实现时的注意事项做了说明:

    (1)如果对象在equals()中使用的信息都没有改变,那么hashCode()值始终不变。

    (2)如果两个对象使用equals()方法判断为相等,则hashCode()方法也应该相等。

    (3)如果两个对象使用equals()方法判断为不相等,则不要求hashCode()也必须不相等;

String的hashcode方法:

public static int hashCode(byte[] value) {
        int h = 0;
        for (byte v : value) {
            h = 31 * h + (v & 0xff);
        }
        return h;
    }
String的hashcode方法使用了字符串本身作了处理后返回一个int数,这是为了尽量使不同的对象拥有不同的hashcode值,以提高在hash码在哈希表中的效率。如hashmap和hashset等。所以在重写hashcode的时候要合理重写hashcode方法,如果会很多对象的hashcode值一样,会导致hashmap的效率大大降低。    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值