文章目录
参考视频
1.Object:所有类的根类(位于最顶层)
Object类是所有类的根类,所有的类在被创建时,会默认继承Object类(extends)
Object类中有两个比较重要的方法:
- Object.toString( ):返回"类全限定名+对象地址"
- Object.hashCode( ):返回"对象的hash值"
- Object.equals(Object):判断两个对象的地址是否相同,返回布尔值
通常在创建一个类之后,都需要重写这三个方法
1.1. Object.toString()
该方法返回对象对应的"类全限定名 + 对象地址"
重写toString()方法:使其输出对象的成员变量
IDEA可以自动重写toString()方法,alt + Ins
一起按,弹出窗口
重写完毕的代码结构如下(参考):
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex=" + sex +
'}';
}
1.2.Object.hashCode()
该方法返回"对象的hash值",不同的对象有着不同的地址,因此哪怕成员变量值相等,Object.hashCode()的返回值仍在一般情况下不相同(小概率会相同)
重写hashCode()方法:使成员变量值相等的对象拥有相等的hash值
IDEA可自动重写,重写完毕后代码如下:
@Override
public int hashCode() {
return Objects.hash(name, sex);
}
这里调用了Objects工具类的hash方法,该方法依照传入的参数值来计算并返回hash值,使得不同对象只要拥有相同的变量值,就判断其hash值相等
特别注意:在重写hashCode( )方法后,hash相同并不代表两个对象相等:
-
首先计算时,不同的值有可能计算出相同的hash;
-
有可能出现:不同类的对象,恰好其传入的参数值相等,结果显示不同类的对象却拥有相同的hash值
1.3.Object.equals(Object)
该方法会判断两个对象的地址是否相同,并返回布尔值
该方法的源码非常简单粗暴:
因而,尽管两个对象类型一致,成员变量值也一致,但由于地址不同,最终判定的结果仍然为false
重写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);
}
可以看到,重写后的判断逻辑如下
- 若地址一致时,直接返回true,否则进入下一步
- 若传入参数为空,返回false;通过反射判断类型,若类型不同,返回false。若二者都不是,进入下一步
- 将传入的对象向下转型(目的是为了使用子类对象的成员变量)
- 逐个比较两个对象的所有成员变量,若都相同,返回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)
相当于:
// 判断地址是否相同,这里包括了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;
}
}
- 先判断地址(这里包括了二者为空的情况)
- 再判断a是否为空
- 调用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();
}
}
运行结果如下: