equals方法详解

123 阅读8分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第22天,点击查看活动详情

哈喽,大家好!我是Why,一名在读学生,目前刚刚开始进入自己的编程学习生涯。虽然学习起步较晚,但我坚信做了才有0或1的可能。学了一段时间以后也是选择在掘金上分享自己的日常笔记,也希望能够在众多道友的大家庭中打成一片。 本文主要讲解equals方法详解,如果大家读后觉得有用的话,还请大家多多支持博主:欢迎 ❤️点赞👍、收藏⭐、留言💬 ✨✨✨个人主页:JinHuan

equals方法

 /*
     关于Object类中的equals方法
         1equals方法的源代码
             public boolean equals(Object obj) {
                 return (this == obj);
             }
             以上这个方法是Object类的默认实现。
                 
         
         2、SUN公司设计equals方法的目的是什么?
             以后编程的过程当中,都要通过equals方法来判断两个对象是否相等。
             equals方法是判断两个对象是否相等的。
         
         3、我们需要研究一下Object类给的这个默认的equals方法够不够用!!!!
                 在Object类中的equals方法当中,默认采用的是“==”判断两个java对象
                 是否相等。而“==”判断的是两个java对象的内存地址,我们应该判断
                 两个java对象的内容是否相等。所以老祖宗的equals方法不够用,
                 需要子类重写equals。
         
         4、判断两个java对象是否相等,不能使用“==”,因为“==”比较的是两个
         对象的内存地址。
         
         5、建议所有子类重写equals方法(注意使用instance of)
 */

栗子

 public class Test02{
     public static void main(String[] args){
 ​
         // 判断两个基本数据类型的数据是否相等直接使用“==”就行。
         int a = 100;
         int b = 100;
         // 这个“==”是判断a中保存的100和b中保存的100是否相等。
         System.out.println(a == b); //true(相等) false(不相等)
 ​
         // 判断两个java对象是否相等,我们怎么办?能直接使用“==”吗?
         // 创建一个日期对象是:2008年8月8日。
         MyTime t1 = new MyTime(2008, 8, 8); //MyTime t1 = 0x1234;
         // 创建了一个新的日期对象,但表示的日期也是:2008年8月8日。
         MyTime t2 = new MyTime(2008, 8, 8); //MyTime t2 = 0x3698;
         
         //测试以下,比较两个对象是否相等,能不能使用“==”???
         // 这里的“==”判断的是:t1中保存的对象内存地址和t2中保存的对象内存地址是否相等。
         System.out.println(t1 == t2); // false
         
         // 重写Object equals方法之前(比较的是对象内存地址)
         /*
         boolean flag = t1.equals(t2);
         System.out.println(flag); //false
         */
         
 ​
         // 重写Object equals方法之后(比较的是内容。)
         boolean flag = t1.equals(t2);
         System.out.println(flag); //true
 ​
         // 再创建一个新的日期
         MyTime t3 = new MyTime(2008, 8, 9);
         // 两个日期不相等,就是false。
         System.out.println(t1.equals(t3)); // false
 ​
         // 我们这个程序有bug吗?可以运行,但是效率怎么样?低(怎么改造。)
         MyTime t4 = null;
         System.out.println(t1.equals(t4)); //false
     }
 }
 ​
 class MyTime { //extends Object{
     int year;
     int month;
     int day;
 ​
     public MyTime(){
     
     }
     public MyTime(int year, int month, int day){
         this.year = year;
         this.month = month;
         this.day = day;
     }
 ​
     // 默认的equals方法
     /*
     public boolean equals(Object obj) {
         return (this == obj);
     }
     */
 ​
     /*
     // 重写Object类的equals方法
     // 怎么重写?复制粘贴。相同的返回值类型、相同的方法名、相同的形式参数列表。
     // equals到底应该怎么重写?你自己定,你认为两个对象什么相等的时候表示相等,你就怎么重写。
     public boolean equals(Object obj) {
         // 当年相同,月相同,并且日也相同的时候,表示两个日期相同。两个对象相等。
         // 获取第一个日期的年月日
         int year1 = this.year;
         int month1 = this.month;
         int day1 = this.day;
 ​
         // 获取第二个日期的年月日
         //int year2 = obj.year;
         //int month2 = obj.month;
         //int day2 = obj.day;
 ​
         if(obj instanceof MyTime){
             MyTime t = (MyTime)obj;
             int year2 = t.year;
             int month2 = t.month;
             int day2 = t.day;
             if(year1 == year2 && month1 == month2 && day1 == day2){
                 return true;
             }
         }
         // 程序能够执行到此处表示日期不相等。
         return false;
     }
     */
 ​
     /*
     // 改良equals方法
     public boolean equals(Object obj) {
         // 如果obj是空,直接返回false
         if(obj == null){
             return false;
         }
         // 如果obj不是一个MyTime,没必要比较了 ,直接返回false
         if(!(obj instanceof MyTime)){
             return false;
         }
         // 如果this和obj保存的内存地址相同,没必要比较了,直接返回true。
         // 内存地址相同的时候指向的堆内存的对象肯定是同一个。
         if(this == obj){
             return true;
         }
         // 程序能够执行到此处说明什么?
         // 说明obj不是null,obj是MyTime类型。
         MyTime t = (MyTime)obj;
         if(this.year == t.year && this.month == t.month && this.day == t.day){
             return true;
         }
 ​
         // 程序能到这里返回false
         return false;
     }
     */
 ​
     
     //再次改良。
     /*
     public boolean equals(Object obj) {
         // 如果obj是空,直接返回false
         if(obj == null){
             return false;
         }
         // 如果obj不是一个MyTime,没必要比较了 ,直接返回false
         if(!(obj instanceof MyTime)){
             return false;
         }
         // 如果this和obj保存的内存地址相同,没必要比较了,直接返回true。
         // 内存地址相同的时候指向的堆内存的对象肯定是同一个。
         if(this == obj){
             return true;
         }
         // 程序能够执行到此处说明什么?
         // 说明obj不是null,obj是MyTime类型。
         MyTime t = (MyTime)obj;
         return this.year == t.year && this.month == t.month && this.day == t.day ;
     }
     */
 ​
     public boolean equals(Object obj) {
         if(obj == null || !(obj instanceof MyTime)){
             return false;
         }
         if(this == obj){
             return true;
         }
         MyTime t = (MyTime)obj;
         return this.year == t.year && this.month == t.month && this.day == t.day ;
     }
 ​
 }
 ​
 /*
 class Person{
     private String idCard;
 }
 */
String中的Equals?
 ​
 /*
     java语言当中的字符串String有没有重写toString方法,有没有重写equals方法。
 ​
     总结:
         1、String类已经重写了equals方法,比较两个字符串不能使用==,必须使用equals。
         equals是通用的。
 ​
         2、String类已经重写了toString方法。
     
     大结论:
         java中什么类型的数据可以使用“==”判断
             java中基本数据类型比较是否相等,使用==
 ​
         java中什么类型的数据需要使用equals判断
             java中所有的引用数据类型统一使用equals方法来判断是否相等。
         
         这是规矩。
 */
 public class Test03{
     public static void main(String[] args){
 ​
         // 大部分情况下,采用这样的方式创建字符串对象
         String s1 = "hello";
         String s2 = "abc";
 ​
         // 实际上String也是一个类。不属于基本数据类型。
         // 既然String是一个类,那么一定存在构造方法。
         String s3 = new String("Test1");
         String s4 = new String("Test1");
         // new两次,两个对象内存地址,s3保存的内存地址和s4保存的内存地址不同。
         // == 判断的是内存地址。不是内容。
         System.out.println(s3 == s4); // false
 ​
         // 比较两个字符串能不能使用双等号?
         // 不能,必须调用equals方法。
         // String类已经重写equals方法了。
         System.out.println(s3.equals(s4)); // true
 ​
         // String类有没有重写toString方法呢?
         String x = new String("尽欢");
         // 如果String没有重写toString()方法,输出结果:java.lang.String@十六进制的地址
         // 经过测试:String类已经重写了toString()方法。
         System.out.println(x.toString()); //尽欢
         System.out.println(x); //尽欢
     }
 }
String的equals
 ​
 // String对象比较的时候必须使用equals方法。
 public class Test04{
     public static void main(String[] args){
         /*
         Student s1 = new Student(111, "北京大兴亦庄二小");
         Student s2 = new Student(111, "北京大兴亦庄二小");
         System.out.println(s1 == s2); // false
         System.out.println(s1.equals(s2)); // true
         */
 ​
         Student s1 = new Student(111, new String("北京大兴亦庄二小"));
         Student s2 = new Student(111, new String("北京大兴亦庄二小"));
         System.out.println(s1 == s2); // false
         System.out.println(s1.equals(s2)); // true
     }
 }
 ​
 class Student{
     // 学号
     int no; //基本数据类型,比较时使用:==
     // 所在学校
     String school; //引用数据类型,比较时使用:equals方法。
 ​
     public Student(){}
     public Student(int no,String school){
         this.no = no;
         this.school = school;
     }
 ​
     // 重写toString方法
     public String toString(){
         return "学号" + no + ",所在学校名称" + school;
     }
 ​
     // 重写equals方法
     // 需求:当一个学生的学号相等,并且学校相同时,表示同一个学生。
     // 思考:这个equals该怎么重写呢?
     // equals方法的编写模式都是固定的。架子差不多。
     public boolean equals(Object obj){
         if(obj == null || !(obj instanceof Student)) return false;
         if(this == obj) return true;
         Student s = (Student)obj;
         return this.no == s.no && this.school.equals(s.school);
 ​
         //字符串用双等号比较可以吗?
         // 不可以
         //return this.no == s.no && this.school == s.school;
     }
 }
 ​

equals的实例

 ​
 // equals方法重写的时候要彻底。
 ​
 public class Test05{
     public static void main(String[] args){
         
         // 多态(自动类型转换。)
         Object o1 = new String("hello world!");
         Object o2 = new User();
         Object o3 = new Address();
 ​
         User u1 = new User("zhangsan", new Address("北京","大兴区","11111"));
         User u2 = new User("zhangsan", new Address("北京","大兴区","11111"));
 ​
         System.out.println(u1.equals(u2)); // true
 ​
         User u3 = new User("zhangsan", new Address("北京","朝阳区","11112"));
         System.out.println(u1.equals(u3)); // false
     }
 }
 ​
 class User{
     // 用户名
     String name; 
     // 用户的住址
     Address addr;
 ​
     public User(){
     }
     public User(String name, Address addr){
         this.name = name;
         this.addr = addr;
     }
 ​
     // 重写equals方法
     // 重写规则:当一个用户的用户名和家庭住址都相同,表示同一个用户。
     // 这个equals判断的是User对象和User对象是否相等。
     public boolean equals(Object obj){
         // 用户名和用户名相同,住址和住址相同的时候,认定是同一个用户。
         if(obj == null || !(obj instanceof User)) return false;
         if(this == obj) return true;
         
         User u = (User)obj;
         if(this.name.equals(u.name) && this.addr.equals(u.addr)){
             return true;
         }
         return false;
     }
 }
 ​
 class Address{
     String city;
     String street;
     String zipcode;
 ​
     public Address(){
     
     }
     public Address(String city,String street,String zipcode){
         this.city = city;
         this.street = street;
         this.zipcode = zipcode;
     }
 ​
     // 注意:这里并没有重写equals方法。
     // 这里的equals方法判断的是:Address对象和Address对象是否相等。
     public boolean equals(Object obj){
         if(obj == null || !(obj instanceof Address)) return false;
         if(this == obj) return true;
         // 怎么算是家庭住址相同呢?
         // 城市相同,街道相同,邮编相同,表示相同。
         Address a = (Address)obj;
         if(this.city.equals(a.city) 
             && this.street.equals(a.street) 
             && this.zipcode.equals(a.zipcode)){
             return true;
         }
         return false;
     }
 }