Java-重写toString方法和equals方法
Object类作为java的根类,是所有类的直接或者间接父类,这意味着,当我们创建一个类,这个类就自动继承了Object的方法。在Object类中,定义了许多方法,其中有2个方法:
从jdk开发手册中可以了解到,对于一个类,默认的toString方法是返回一个字符串,形式为“类名@十六进制数”,这其中的十六进制数是一个哈希码的十六进制,可以唯一标识一个对象。
package com.day12.package05Object;
public class Main {
public static void main(String[] args) {
Student s1 = new Student("王小明", 20);
Student s2 = new Student("王小明", 20);
System.out.println(s1);
System.out.println(s2);
}
}
输出:
可以看到,对于两个不同的对象,后面的十六进制数是不同的。
在前面的jdk开发手册中写到,默认的toString()方法返回对象的字符串表示形式,而且建议类重写这个方法。在实际的学习和工作中,我们可能更想看到对象的属性信息,如上面的Student类,可能更想看到关于姓名和年龄的信息,这个时候,我们可能会自己写一个方法来输出对象的信息,就像下面的形式:
public void show(){
System.out.println("姓名:"+name+" 年龄:"+age);
}
通过对象调用show()方法就可以输出对象的属性信息。
从toString()方法的意义和官方建议来看,我们也可以通过重写toString()方法来输出对象的属性信息,例如把上面那段代码的“show”改为“toString”,就是对toString()方法的重写。在Intellij IDEA中,在类里面打出“toString”可以自动生成这个类重写的toString()方法。
//IDEA自动生成重写的toString方法。
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
对toString方法重写后,再次运行Main类中的main()方法,查看输出:
可以看到,输出的是对象的属性信息,这样的信息比较直观,我们可能更需要这样的信息。
在jdk开发手册中,注意到,Object类的equals方法是当且仅当两个引用指向相同的对象,两个引用才会相等,即equals()方法返回true,除此之外都返回false。
public class Main {
public static void main(String[] args) {
Student s1 = new Student("王小明", 20);
Student s2 = new Student("王小明", 20);
System.out.println(s1.equals(s2));
Student s3=s2;
System.out.println(s2.equals(s3));
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
}
}
在上面的代码中,s1和s2的name和age的值都是相等的(Student的成员变量只有name和age),但即使如此,从默认的equals()方法的说明也可以预测输出是第一个是false,第二个是true。
因为equals()当且仅当两个引用指向同一个对象才回返回true,s1和s2指向的是两个不同的对象,因此返回false,而s3和s2指向同一个对象,返回true。查看上面代码的输出:
可以看到,第一个为flase,第二个为true,因为s1和s2指向的对象是不同的,s2和s3指向的对象是相同的。
在实际应用中,如果我们不知道equal()这个方法的用法,我们可能就会用来比较两个对象的属性值是否完全相同,这可能造成逻辑错误。而了解equals()方法的,可能就会自己在类里面写一个方法来判断两个对象的属性值是否相同,这是可以的,也是应该的。就像toString()方法一样,我们可以通过重写equals()方法来判断两个对象的属性值,我们可以自己手动写,也可以通过集成开发平台来帮我们自动生成,在IDEA中,打出“equals”时会提示重写equals方法,如下,IDEA帮我重写Student类的equals()方法:
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
这段代码的逻辑是这样的:
1.比较地址是否相同(引用的对象是否为同一个对象)
2.判断要比较的对象是否为null,判断两个对象是否来自同一个类
3.向下转型,因为o是Object类型的引用,转为Student类型的,以便于能够访问Student类的属性
4.判断本对象的属性和o指向的对象的属性是否都相同。
重写equals()方法后,再次运行main()方法,查看输出:
可以看到,这次s1.equals(s2)和s2.equals(s3)的返回值都是true,因为重写equals方法后,比较的不再是两个引用指向的对象是否相同,而是两个对象的属性是否完全一致。
在实际的应用中,我们可以通过重写equals()方法来满足我们实际的需要,比如更改默认的equals()方法的参数Object为其他类型的,或者更改代码的逻辑,比如有时也许不需要比较所有的属性值等等。