equals和==区别

== ,比较的是两个引用对象是否指向同一块内存
equals ,比较的是两个字符串的值是否相等


一、 equals 和 ==区别:

1. 判断两个String对象是否相等

当我们通过new关键字来创建对象时,就会在堆里面分配一块空间。

代码块:
public class Test {
    public static void main(String[] args) {
        String str1 = new String("123");
        String str2 = new String("123");
        System.out.println(str1 == str2);
        System.out.println(str1.equals(str2));  
    }
}
内存图:

这里写图片描述

代码运行结果:

这里写图片描述
因为这两个引用对象str1,str2引用的是不同的两块内存,所以==比较结果为false。

由于默认继承于Object类的equals方法,但是String类重写了equals方法,String比较的是两个字符串的值是否相等,与内存地址是否相等没关系,而字符串str1和str2的值都是123,所以为true。

结论:

== 比较,比较的是两个引用对象是否指向同一块内存
equals 比较,比较的是两个字符串的值是否相等

2. 判断两个自定义对象是否相等
代码块:
public class Test {
    public static void main(String[] args) {
        Person p1 = new Person(1,"S");
        Person p2 = new Person(1,"S");
        System.out.println(p1 == p2);
        System.out.println(p1.equals(p2));
    }
}

class Person{
    int id;
    String name;
    public Person(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
}
代码运行结果:

这里写图片描述

2.1 详解:

System.out.println(p1 == p2);
== 比较的是两块引用所指向的内存地址,显然通过new来创建的两个对象在内存中会分配两块内存空间,所以为 false.

对于equals方法,因为默认继承于Object的equals方法,而Person类中并没有重写equals方法,所以当比较p1.equals(p2))时,通过调用Object类中的equals方法来进行比较,而Object类中的equals方法比较是通过内存地址来比较的,就是说内存地址相等(p1==p2),则equals为true,反之为false。
显然p1与p2的内存地址不相等,则为false。
所以一般我们都会重写equals()方法(重写代码下面有详解)

注意: 这里可能会对内存地址和hashCode概念有所混淆
即使重写hashCode方法,使得hashcode值相等,但是p1与p2的内存地址任然不相等,比较的是内存地址,不是hashCode值是否相等,有关内存地址与hashCode关系下面有简单提到。

所以当我重写hashCode()方法,并使得返回的值相等,p1.equals(p2))的值仍然为false。举例说明:

public class Test {
    public static void main(String[] args) {
        Person p1 = new Person(1,"S");
        Person p2 = new Person(1,"S");
        System.out.println(p1 == p2);  // false
        System.out.println(p1.hashCode()+","+p2.hashCode()); // 1,1
        System.out.println(p1.equals(p2));  // false

    }
}

class Person{
    int id;
    String name;

    public Person(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    @Override
    public int hashCode() {
        return 1;
    }
}

运行结果:

false
1,1
false

2.2 重写equals()方法:

equals()方法我们一般不使用继承自Object类来判断,而是通过IDEA工具来生成已经@Override 的equals()方法。

当此equals()方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

hashCode()方法我们一般不使用Object类的,而是通过IDEA工具来生成已经@Override 的方法。

代码块:
public class Test {
    public static void main(String[] args) {
        Person p1 = new Person(1,"S");
        Person p2 = new Person(1,"S");
        System.out.println(p1 == p2);
        System.out.println(p1.equals(p2));
    }
}

class Person{
    int id;
    String name;

    public Person(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }   
}
代码详解:

if (this == obj)
return true;

== 比较的是两个引用对象是否指向同一块内存,显然p1和p2引用的是两块内存空间,所以return false;

  if (obj == null)
    return false;

当传入的参数对象 obj 为null,则一定为false。

  if (getClass() != obj.getClass())
        return false;

当两个对象不是一个Class,则为false。

Person other = (Person) obj;

当上个条件getClass() != obj.getClass() 不满足,即属于同一个Class时,把obj的类型Object转化为Person类型

  if (id != other.id)
        return false;
    if (name == null) {
        if (other.name != null)
            return false;
    } else if (!name.equals(other.name))
        return false;
    return true;

通过转化为Person后,对属性进行比较。相等则为true,反之为false

二、 HashCode 和 内存地址 关系:

如果没有人为的修改生成的HashCode值,那么 可以理解 HashCode 是内存地址,或者可以说HashCode就是内存地址。
但是 当重写HashCode方法,并修改了HashCode值后,此时内存地址不能理解为HashCode了。

来自生活的例子理解:
要想找到刘德华住在哪里,可以通过以下两种来找。
一、住在上海浦东新区纳贤路799号(相当于内存地址),二、上海浦东新区益江小区第三排第二列的5楼(相当于hashcode)。

同理要想找到黄日华住在哪里,可以通过以下两种来找。
一、住在上海浦东新区纳贤路600号(相当于内存地址),二、上海浦东新区益江小区第三排第一列的3楼(相当于hashcode)。

当我们想要找刘德华时,可以通过上海浦东新区益江小区第三排第二列的5楼(相等于hashcode)对应上海浦东新区纳贤路799号(相当于内存地址),从而找到刘德华这个人。此时可以理解为内存地址是hashcode。

但是当我们修改上海浦东新区益江小区第三排第二列的5楼(相当于hashcode) 为上海浦东新区益江小区第三排。修改上海浦东新区益江小区第三排第一列的3楼(相当于hashcode) 为上海浦东新区益江小区第三排,并没有具体的详细的地址,此时,黄日华和刘德华的hashcode相等,但是他们的内存地址不相等。所以此时,不能理解为内存地址是hashcode。

代码举例: 不修改hashCode()方法,默认调用Object类的hashCode()方法
public class Test {
    public static void main(String[] args) {    
        Person p1 = new Person(1,"S");
        Person p2 = new Person(1,"S");
        System.out.println(p1 == p2);
        System.out.println(p1.hashCode()+","+p2.hashCode());    
    }
}

class Person{
    int id;
    String name;
    public Person(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }               
}

运行结果:

false
1704856573,705927765

(因为分配了两块内存)内存地址不相等,HashCode值不相等

但是当我重写HashCode方法,并使得返回的哈希码值相等,此时内存地址不能理解为HashCode了。

举例:
public class Test {
    public static void main(String[] args) {    
        Person p1 = new Person(1,"S");
        Person p2 = new Person(1,"S");
        System.out.println(p1 == p2);  // false
        System.out.println(p1.hashCode()+","+p2.hashCode());     //值相等
    }
}

class Person{
    int id;
    String name;

    public Person(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    @Override
    public int hashCode() {
        return 1;
    }           
}

运行结果:

false
1,1

但是两个对象引用同一块内存地址,引用同一个对象时,此时内存地址相等,hashcode值也相等

举例:
public class Test {
    public static void main(String[] args) {    
        Person p1 = new Person(1,"S");
        Person p2 = p1;
        System.out.println(p1 == p2);  // true
        System.out.println(p1.hashCode()+","+p2.hashCode());     //值相等
    }
}

class Person{
    int id;
    String name;

    public Person(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }           
}

运行结果:

true
1704856573,1704856573

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值