对象比较“==”与“hashCode()”的孽缘(java 小虚竹)

举报
小虚竹 发表于 2022/08/29 22:52:02 2022/08/29
【摘要】 ❤️作者主页:小虚竹 ❤️作者简介:大家好,我是小虚竹。Java领域优质创作者🏆,CSDN博客专家🏆,华为云享专家🏆,掘金年度人气作者🏆,阿里云专家博主🏆 ❤️技术活,该赏 ❤...

❤️作者主页:小虚竹

❤️作者简介:大家好,我是小虚竹。Java领域优质创作者🏆,CSDN博客专家🏆,华为云享专家🏆,掘金年度人气作者🏆,阿里云专家博主🏆

❤️技术活,该赏

❤️点赞 👍 收藏 ⭐再看,养成习惯

PC端左侧加我微信,进社群,有送书等更多活动!

问题

有个粉丝问虚竹哥:为什么内存地址一样,但比较用“==”时,结果是false;
比较用equals()时,得到的结果是true。
在这里插入图片描述

分析

虚竹哥刚开始也是一脸懵,使用clone方法 克隆出来的对象是新对象,(深入解析题目:【第33题】JAVA高级技术-对象克隆2(浅克隆)
内存地址怎么可能会一样?
但是粉丝就是截图出来了,有图有真相是吧
难道是我记错了?
我不信!
写个代码验证下:
Address类

package com.xiaoxuzhu;

/**
 * Description: 
 *
 * @author zenghw
 * @version 1.0
 *
 * <pre>
 * 修改记录:
 * 修改后版本	        修改人		修改日期			修改内容
 * 2022/8/23.1	    zenghw		2022/8/23		    Create
 * </pre>
 * @date 2022/8/23
 */
public class Address {
    private String state; // 表示员工所在的国家
    private String province;// 表示员工所在的省
    private String city; // 表示员工所在的市

    public Address(String state, String province, String city) {// 利用构造方法进行初始化
        this.state = state;
        this.province = province;
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {// 重写toString()方法
        StringBuilder sb = new StringBuilder();
        sb.append("国家:" + state + ", ");
        sb.append("省:" + province + ", ");
        sb.append("市:" + city);
        return sb.toString();
    }
}



  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

Employee类:

package com.xiaoxuzhu;

/**
 * Description: 
 *
 * @author zenghw
 * @version 1.0
 *
 * <pre>
 * 修改记录:
 * 修改后版本	        修改人		修改日期			修改内容
 * 2022/8/23.1	    zenghw		2022/8/23		    Create
 * </pre>
 * @date 2022/8/23
 */
public class Employee implements Cloneable {
    private String name; // 表示员工的姓名
    private int age; // 表示员工的年龄
    private Address address;// 表示员工的地址

    public Employee(String name, int age, Address address) {// 利用构造方法进行初始化
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public Employee clone() {// 实现浅克隆
        Employee employee = null;
        try {
            employee = (Employee) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return employee;
    }
}



  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

再写个测试类:

package com.xiaoxuzhu;

/**
 * Description: 
 *
 * @author zenghw
 * @version 1.0
 *
 * <pre>
 * 修改记录:
 * 修改后版本	        修改人		修改日期			修改内容
 * 2022/8/23.1	    zenghw		2022/8/23		    Create
 * </pre>
 * @date 2022/8/23
 */
public class Test {
    public static void main(String[] args) {
        Address address = new Address("中国", "福建", "厦门");// 创建address对象
        Employee employee1 = new Employee("小虚竹", 30, address);// 创建employee1对象
        Employee employee2 = employee1.clone();
        System.out.println(employee1);
        System.out.println(employee2);
        System.out.println(employee1 == employee2);
    }

}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

在这里插入图片描述
clone克隆后的对象,内存地址是不一样的。虚竹哥拍了拍胸膛,安心了。
但为什么粉丝得到了内存地址一样的对象呢?
经常虚竹哥跟粉丝的沟通,终于找到问题了
在这里插入图片描述
问题出在重写了equals方法,也重写了hashCode方法。
在打印对象时,发生了什么?可以来分析下

System.out.println(employee1);

在这里插入图片描述
首先是调用PrintStream.println 方法,方法里对要打印的对象进行转化成字符串。
在这里插入图片描述
String.valueOf 方法对入参对象进行判空处理,如果为null时,返回字符串“null”。如果不是null,则调用对象的toString() 方法。
一开始对Employee类 没有重写toString() 方法。 所以这里会进入Object对象toString() 方法。
在这里插入图片描述

打印的是employee1对象所继承的Object类中的hashCode方法返回的值。
在这里插入图片描述
但我们发现这个对象已经是native了,至于Object 的hashCode方法是如何取值的,大家可自行去看下源码,如何看源码传送门

可知:不同的对象产生的hashCode是不同的;默认情况下,对象的hashCode是通过将该对象的内部地址转换成一个整数来实现的。

好了,分析了这么多,回到粉丝的问题上来:
在这里插入图片描述
问题出在重写了equals方法,也重写了hashCode方法。
因为粉丝把hashCode方法重写了,导致得到的hashCode值并不代表着内存地址了。

System.out.println(employee1 == employee2);
这里是内存地址的比较

才会让人有一种错觉!内存地址(输出)明明一样,用比较“==”得到了false。

四、推荐专栏

《JAVA从零到壹》

《JAVA筑基100例》

我是虚竹哥,我们下期见~~~

文章来源: xiaoxuzhu.blog.csdn.net,作者:小虚竹,版权归原作者所有,如需转载,请联系作者。

原文链接:xiaoxuzhu.blog.csdn.net/article/details/126493372

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。