Object 是一个具体的类,但它主要是为扩展而设计的。它的所有非 final 方法(equals、hashCode、toString、clone 和 finalize)都有显式的通用约定,因为它们的设计目的是被覆盖。任何类都有责任覆盖这些方法并将之作为一般约定;如果不这样做,将阻止依赖于约定的其他类(如 HashMap 和 HashSet)与之一起正常工作。
一个类要么默认继承了 Object 类,要么间接继承了 Object 类,Object 类是 Java 中的祖宗类。Object 类的方法是一切子类都可以直接使用的。
Object 类的常用方法:
toString
public String toString():默认是返回当前对象在堆内存中的地址信息:类的全限名@内存地址,例如 entity.Student@34ce8af7
public class ObjectTest {public static void main(String[] args) {Student student = new Student("Halo", '男', 18);System.out.println(student.toString());// 直接输出对象变量,默认可以省略 toString()System.out.println(student);}}
- 开发中直接输出对象,默认输出对象的地址其实是毫无意义的。
- 开发中输出对象变量,更多的时候是希望看到对象的内容数据而不是对象的地址信息。
父类 toString() 方法存在的意义就是为了被子类重写,以便返回对象的内容信息,而不是地址信息。
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
'}';
}
IDEA 中使用 Alt + Ins 或输入 tos 调用重写方法
equals
public Boolean equals(Object o):默认是比较当前对象与另一个对象的地址是否相同,相同返回 true,不同返回 false。
若直接比较两个对象的地址是否相同完全可以用“==”替代 equals。
父类 equals 方法存在的意义就是为了被子类重写,以便子类自己来定制比较规则。
@Override
public boolean equals(Object o) {
// 判断是否是同一个对象
if (this == o) {
return true;
}
// 如果 o 是 null、o 不是 this 对应类型返回 false
if (o == null || getClass() != o.getClass()) {
return false;
}
Student student = (Student) o;
return sex == student.sex && age == student.age && Objects.equals(name, student.name);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Student)) {
return false;
}
Student student = (Student) o;
return sex == student.sex && age == student.age && Objects.equals(name, student.name);
}
注:在重写的 equals 进行字符串比较时,没有对象自己的 equals 方法,而是选择了 Objects 的 equals 方法来比较两个对象。Object.equals() 方法比较的结果是一样的,但是更安全。
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
以上两种重写 equals 的方式区别在与 x.getClass() == y.getClass() 和 x instanceof y
getClass() 返回一个对象所属的类,返回的是一个类名,不会判断子类与父类的继承关系:
public class Human {
private String name;
private char sex;
private int age;
public Human(String name, char sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public Human() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Student extends Human {
private int grade;
private int id;
public Student(String name, char sex, int age) {
super(name, sex, age);
}
public Student(String name, char sex, int age, int grade, int id) {
super(name, sex, age);
this.grade = grade;
this.id = id;
}
public Student() {
}
public Student(int grade, int id) {
this.grade = grade;
this.id = id;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
public static void main(String[] args) {
Student student = new Student("Halo", '男', 18);
Human human = new Human("Halo", '男', 18);
System.out.println(student.getClass());
System.out.println(human.getClass());
}
// OutPut:
// class entity.Student
// class entity.Human
instanceof 比较一个对象是否是该类的实例:
public static void main(String[] args) {
Student student = new Student("Halo", '男', 18);
Human human = new Human("Halo", '男', 18);
System.out.println(student.getClass() == human.getClass()); // false
System.out.println(student instanceof Object); // true
System.out.println(student instanceof Student); // true
System.out.println(student instanceof Human); // true
System.out.println(human instanceof Student); // false
}
instanceof 会判断继承关系,子对象 instanceof 父类 会返回 true,父对象 instanceof 子类会返回 false。 可以理解为判断两个问题:你是这个类吗? 你是这个类的派生类吗?
故使用 instanceof 判断,则以下结果返回 true,而 getClass 方法判断则会返回 false
public static void main(String[] args) {
Student student = new Student("Halo", '男', 18);
Human human = new Human("Halo", '男', 18);
System.out.println(human.equals(student));
}
equals 的最佳实践 TODO
equals 方法需要具有下面特性:
- 自反性:对于任何非 null 的参考值 x,
x.equals(x)必须返回 true。 - 对称性:对于任何非 null 参考值 x 和 y,
x.equals(y)必须在且仅当y.equals(x)返回 true 时返回 true。 - 传递性:对于任何非 null 的引用值 x, y, z,如果
x.equals(y)返回 true,y.equals(z)返回 true,那么x.equals(z)必须返回 true。 - 一致性:对于任何非 null 的引用值 x 和 y,只要
equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)就会一致地返回 true,或者一致地返回 false。 对于任意非空引用 x,
x.equals(null)应该返回 false。参考 链接、《Effective Java》第3版
