Java基础 -equals方法

    Object类中的equals方是用来判断一个对象等于另一个对象,至于这个等于的条件需要自己定义,比如说,String类的equals相等的条件就是字符串的内容必须相同,equals方法返回的值才为true。所以在我们在自己定义的类中,equals的重写是常见的!这里主要展示equals的特性和equals的正确写法,至于equals方法具体的含义这里不介绍!

1. 举一个例子

    在这介绍其他的,我们先来看看正确的写法

public class Animal {
    private String name = null;

    public Animal(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    @Override
    public boolean equals(Object obj) {
        if(this == obj) {
            return true;
        }
        if(obj == null) {
            return false;
        }
        if(this.getClass() != obj.getClass()) {
            return false;
        }
        Animal animal = (Animal) obj;
        //return this.name.equals(animal.name);
        //这个方法只在JDK7及其以后才有的
        //这个方法能够保证两个name其中只有一个为null的话,返回的false
        //如果两个都为null的话,返回的是true
        //如果两个都不为null的话,具体看情况
        return Objects.equals(this.name, animal.name);
    }
}

    从上面的代码中我们看到是,Animal类的equals方法判断的相等条件是name是否为相同。说实话,判断的条件非常的简单,但是我们的代码写的非常复杂。可能有人会这样写的:

    public boolean equals(Object obj) {
        if(! (obj instanceof Animal)) {
            return false;
        }
        Animal animal = (Animal) obj;
        return this.name.equals(animal.name);
    }

    实际上,上面的代码是有很大的问题,至于有什么问题,待会再说!这里我们来解释一下正确equals方法写的代码:

1. this == obj, 毫无疑问,如果两个对象的内存都是相同的话,那么肯定是同一个对象了。
2. this == null, 同样的话,如果传进来的对象是null的话,肯定为false。
3. this.getClass == obj.getClass, 这个条件可能让人有点疑惑。我来解释一下,getClass是获得当前的对象的Class对象,至于什么是Class对象,这里不解释,需要的记得是:同一类的所有对象的获得的Class对象都是同一个Class对象,也就是说,如果这里的this与obj不属于同一个类的,那么肯定为false。

    那么这种写法有好处呢,等我把列出另一个类的代码再说吧!

public class Dog extends Animal{
    private int age = 0;
    public Dog(String name, int age) {
        super(name);
        this.age = age;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
    @Override
    public boolean equals(Object obj) {
        if(!super.equals(obj)) {
            return false;
        }
        Dog dog = (Dog) obj;
        return this.age == dog.age;
    }
}

    我们发现Dog类继承于Animal类,并且重写了父类的equals方法。在Dog类中equals方法,我们先来判断了这两个对象是否是相等的,其次再比较了age是否相同的。其中先调用了父类的equals来判断,再来判断子类本身的条件,这种方法有几个好处:

1. 符合继承的特性,当且仅当他们通过父类equals才有可能判断子类的条件,因为如果不判断父类的equals的话,当父类的equals返回的是false,但是通过调用子类的equals却返回true。这个根本不符合面向对象的特性,实际点,如果两个儿子老爸都不相同的话,儿子怎么可能相同!
2. 避免了obj是Dog类的子类(虽然这里Dog类没有子类)。因为这里,我们先来调用父类的equals,父类的equals方法中:this.getClass() == obj.getClass 会帮助我们判断这两个类是否是同一个类。按照我们以往的写法,使用instanceof关键字来进行判断的是有很大的问题的,如果this是Dog类的对象,但是obj的实际类型是Dog子类的对象,如果使用 obj instanceof Dog 这个返回的肯定为true,如果通过了我们这个判断语句,最后来判断我们的age。实际上,这两个对象肯定不是同一个对象,所以最后用age来判断是有问题的。至于这个问题的详细解释,待会还会提及!

2. equals方法的特性

    上面留了一些伏笔,这里将详细的解释,但是在解释之前,我们先来看看equals方法的特性:

1. 自反性:对于任何的非空对象,x.equals(x)返回肯定为true。

2. 对称性:对于任何两个非空对象x、y,如果x.equals(y)返回的是true,那么y.equals(x)返回的是肯定也为true。

3. 传递性:对于任何三个非空对象x、y、z,如果x.equals(y)为true,并且y.equals(z),那么x.equals(z)肯定也为true。

4. 一致性:如果对象x和对象y没有发生任何变换的话,反复调用y.equals(x)应该返回的是一样的结果。

5. 对于任意非空对象x,x.equals(null)应该返回的是false。

    针对这些特性,我们拿一个特性来解释为什么使用instanceof关键字来进行判断有很大的问题。
    假设,记住这里是假设:如果Animal类的equals方法和Dog类的equals方法使用的是instanceof关键字来判断的,也就是下面的代码:

Animal类的equals方法:
    @Override
    public boolean equals(Object obj) {
        if(!(obj instanceof Animal)) {
            return false;
        }
        Animal animal = (Animal) obj;
        return Objects.equals(this.name, animal.name);
    }
Dog类的equals方法:
    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Dog)) {
            return false;
        }
        Dog dog = (Dog) obj;
        return this.age == dog.age;
    }
然后我们在main方法里面这么写:
    public static void main(String[] args) {
        Animal a1 = new Animal("pby");
        Dog d1 = new Dog("pby", 21);
        System.out.println(a1.equals(d1));
        System.out.println(d1.equals(a1));
    }

    我们可以看到的是第一个结果返回的true,但是第二个返回的false。这个就有问题了,不符合equals方法的对称性。
    我们来分析一下,当a1.equals(d1)时,调用的Animal类中的equals方法,这个方法对name进行判断,首先d1 instanceof Animal 肯定为true,因为Dog类是Animal的子类,所以if条件没有屏蔽掉d1,由于两个对象的name是相同的,所以返回值是true,但是真正的结果是false,因为他们不属于同一个类!至于第二个为什么是false,这里将不在解释了!
    然后我们回来看正确写法,this.getClass == obj.getClass这个判断就能够将我们的d1屏蔽掉!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,932评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,554评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,894评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,442评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,347评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,899评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,325评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,980评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,196评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,163评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,085评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,826评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,389评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,501评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,753评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,171评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,616评论 2 339

推荐阅读更多精彩内容

  • 1.import static是Java 5增加的功能,就是将Import类中的静态方法,可以作为本类的静态方法来...
    XLsn0w阅读 1,202评论 0 2
  • 面向对象主要针对面向过程。 面向过程的基本单元是函数。 什么是对象:EVERYTHING IS OBJECT(万物...
    sinpi阅读 1,036评论 0 4
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,524评论 18 399
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,616评论 0 11
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,153评论 11 349