Java基础 | 11.toString( )、hashCode( )和equals( ),Objects工具包

参考视频

215 - 218

1.Object:所有类的根类(位于最顶层)

Object类是所有类的根类,所有的类在被创建时,会默认继承Object类(extends)

Object类中有两个比较重要的方法:

  • Object.toString( ):返回"类全限定名+对象地址"
  • Object.hashCode( ):返回"对象的hash值"
  • Object.equals(Object):判断两个对象的地址是否相同,返回布尔值

通常在创建一个类之后,都需要重写这三个方法

1.1. Object.toString()

该方法返回对象对应的"类全限定名 + 对象地址"

image-20220324194851722

重写toString()方法:使其输出对象的成员变量

IDEA可以自动重写toString()方法,alt + Ins一起按,弹出窗口

image-20220324200613069

重写完毕的代码结构如下(参考):

@Override
public String toString() {
    return "Student{" +
        "name='" + name + '\'' +
        ", sex=" + sex +
        '}';
}

1.2.Object.hashCode()

该方法返回"对象的hash值",不同的对象有着不同的地址,因此哪怕成员变量值相等,Object.hashCode()的返回值仍在一般情况下不相同(小概率会相同)

image-20220324200925577

重写hashCode()方法:使成员变量值相等的对象拥有相等的hash值

IDEA可自动重写,重写完毕后代码如下:

@Override
public int hashCode() {
    return Objects.hash(name, sex);
}

这里调用了Objects工具类的hash方法,该方法依照传入的参数值来计算并返回hash值,使得不同对象只要拥有相同的变量值,就判断其hash值相等

特别注意:在重写hashCode( )方法后,hash相同并不代表两个对象相等:

  1. 首先计算时,不同的值有可能计算出相同的hash;

  2. 有可能出现:不同类的对象,恰好其传入的参数值相等,结果显示不同类的对象却拥有相同的hash值

    image-20220324202301824

1.3.Object.equals(Object)

该方法会判断两个对象的地址是否相同,并返回布尔值

该方法的源码非常简单粗暴:

image-20220324202812511

因而,尽管两个对象类型一致,成员变量值也一致,但由于地址不同,最终判定的结果仍然为false

image-20220324203357664

重写equals(Object)方法,使类型一致且成员变量值相等的对象判定为true

IDEA可自动重写,重写完毕后代码如下:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Student student = (Student) o;
    return Objects.equals(name, student.name) &&
        Objects.equals(sex, student.sex);
}

可以看到,重写后的判断逻辑如下

  1. 若地址一致时,直接返回true,否则进入下一步
  2. 若传入参数为空,返回false;通过反射判断类型,若类型不同,返回false。若二者都不是,进入下一步
  3. 将传入的对象向下转型(目的是为了使用子类对象的成员变量)
  4. 逐个比较两个对象的所有成员变量,若都相同,返回true,否则返回false

特别注意:若调用者(本对象)为空,尝试调用equals(Object)就会报NPE

而Objects工具包很好地解决了这个问题:

但前提是必须先重写类的equals(Object)方法,详细见下:

2.Objects:工具包

  • Objects.toString(Object):有效避免NPE
  • Objects.hash(Object…):根据传入的值计算hash值
  • Objects.equals(Object, Object):有效避免NPE

2.1.Objects.equals(Object, Object)

image-20220324204830697

相当于:

// 判断地址是否相同,这里包括了a和b同时为null的情况
if (a == b){
    return true;
}

// 地址不同时
else{
    // 若a不为空,进一步判断
    if (a != null){
        // 调用a.equals(b),如果有重写,将调用重写方法
        if(a.equals(b)){
            return true;
        }
        else{
            return false;
        }
    }
    // 若a为空,直接返回false
    else{
        return false;
    }
}
  1. 先判断地址(这里包括了二者为空的情况)
  2. 再判断a是否为空
  3. 调用a.equals(b)判断(会调用重写方法)

因此在使用Objects.equals(Object, Object)之前,必须要先重写目标类的equals(Object)方法

2.2.Objects工具类搭配三种重写方法

StudentWithOverride.java

package com.xyx_eshang.entity;

import java.util.Objects;

/**
 * @author xyx-Eshang
 */
public class StudentWithOverride {
    private String name;
    private Boolean sex;

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        StudentWithOverride student = (StudentWithOverride) o;
        return Objects.equals(name, student.name) &&
            Objects.equals(sex, student.sex);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, sex);
    }

    @Override
    public String toString() {
        return "StudentWithOverride{" +
            "name='" + name + '\'' +
            ", sex=" + sex +
            '}';
    }

    public String getName() {
        return name;
    }

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

    public Boolean getSex() {
        return sex;
    }

    public StudentWithOverride setSex(Boolean sex) {
        this.sex = sex;
        return this;
    }
}

App.java

package com.xyx_eshang;

import com.xyx_eshang.entity.StudentWithOverride;

import java.util.Objects;

/**
 * Hello world!
 */
public class App {
    public static void testObjectsAndOverride() {
        StudentWithOverride student1 = new StudentWithOverride().setName("小明").setSex(true);
        StudentWithOverride student2 = new StudentWithOverride().setName("小明").setSex(true);

        StudentWithOverride student3 = new StudentWithOverride().setName("小红").setSex(false);
        StudentWithOverride student4 = null;
        StudentWithOverride student5 = null;

        // 1. 重写toString后:
        System.out.println("Objects.toString(student1):" + Objects.toString(student1));
        System.out.println("Objects.toString(student2):" + Objects.toString(student2));
        System.out.println("Objects.toString(student3):" + Objects.toString(student3));
        System.out.println("Objects.toString(student4):" + Objects.toString(student4));
        System.out.println("Objects.toString(student5):" + Objects.toString(student5));

        // 2. 重写hashCode后:
        System.out.println("Objects.hashCode(student1):" + Objects.hashCode(student1));
        System.out.println("Objects.hashCode(student2):" + Objects.hashCode(student2));
        System.out.println("Objects.hashCode(student3):" + Objects.hashCode(student3));
        System.out.println("Objects.hashCode(student4):" + Objects.hashCode(student4));
        System.out.println("Objects.hashCode(student5):" + Objects.hashCode(student5));

        // 3. 重写equals后,当成员变量值相等,直接调用Object.equals():
        System.out.println("student1.equals(student2):" + student1.equals(student2));

        // 4. 重写equals后,当成员变量值相等,调用Objects.equals(Object, Object):
        System.out.println("Objects.equals(student1, student2):" + Objects.equals(student1, student2));
    }


    public static void main(String[] args) {
        testObjectsAndOverride();
    }
}

运行结果如下:

image-20220324210449356

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值