== 与 equals() 详解

Java中有很多基础的知识,但是也是往往容易被人忽略的,本篇文章主要分析不得不提的==equals()这对冤家(面试基本都会被问到吧)。

== 与 equals()


在java中可以分为值类型与引用类型,8种基本数据类型(byte,short,int,long,float,double,boolean,char)就是属于值类型,其他的都是引用类型(包括我们常用的String)
值类型的比较只能通过==来进行比较

if(value == 100) {
    //do something
}

而引用类型既可以通过==比较,也可以通过equals()进行比较,==比较的是两个对象是否指向同一个地址

A a1 = new A();
A a2 = new A();
A a3 = a1;

Log.v("A", a1 == a2 ? "a1 = a2" : "a1 != a2");
Log.v("A", a1 == a3 ? "a1 = a3" : "a1 != a3");
Log.v("A", a2 == a3 ? "a2 = a3" : "a2 != a3");

输出的结果

a1 != a2
a1 = a3
a2 != a3

a1和a2都是new A(),他们指向的是不同的地址,而a1和a3指向的是同一个地址

那我们接下来修改代码看看equals()的结果是不是一样的

A a1 = new A();
A a2 = new A();
A a3 = a1;

Log.v("A", a1.equals(a2) ? "a1 = a2" : "a1 != a2");
Log.v("A", a1.equals(a3) ? "a1 = a3" : "a1 != a3");
Log.v("A", a2.equals.(a3) ? "a2 = a3" : "a2 != a3");

输出的结果

a1 != a2
a1 = a3
a2 != a3

equals()的输出结果跟==是一样的,equals()的实现是在Object里面实现的,看看equals()的源码

 public boolean equals(Object o) {
        return this == o;
 }

也是直接通过==来进行比较的

既然equals()的实现直接是通过==来实现的话,equals()那存在的意义又是什么呢?先看一个例子

private ArrayList<Hat> mShopHats = new ArrayList<>();

  @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    initShopHats();
    gotoBuyHat();
}

 private void initShopHats() {
    mShopHats.add(new Hat("white"));
    mShopHats.add(new Hat("black"));
    mShopHats.add(new Hat("orange"));
    mShopHats.add(new Hat("green"));
    mShopHats.add(new Hat("yellow"));
}

private void gotoBuyHat() {
    Hat needHat = new Hat("white");
    Hat buyHat = buyHat(needHat);
    if(buyHat == null) {
        Log.i("hat","居然买不到 " + needHat.color + " 帽子");
    } else {
        Log.i("hat","买到了一顶 " + buyHat.color + " 帽子");
    }
}

private Hat buyHat(Hat hat){
    for (Hat item: mShopHats) {
        if(hat.equals(item)) {
            return item;
        }
    }
    return null;
}
public class Hat {
    public Hat(String color) {
        this.color = color;
    }
    public String color;
}

上面的代码逻辑大概是这样:首先在mShopHats里面初始化了white、black、orange、green、yellow五种color帽子,然后初始化了一个hat帽子对象,color为white,到商店去买color为white的帽子,再将结果进行打印

 I/hat: 居然买不到 white 帽子

商店明明有白帽子,居然告诉我买不到白帽子,这是为什么呢?就是因为equals()引起的,当我们到商店去买white帽子的时候,程序认为你需要买的帽子是另外一顶white帽子,而不是他们商店里面的那顶white帽子,因此没有买到white帽子。
通过上面的例子,有时候在比较对象的时候,我们只需要比较对象的某些属性相等就认为他们的相等的,就像上面的只要color为white的hat,我们就认为他们是相等的,这恰恰就是equals()存在的原因。

Java设计equals()方法其实是交给开发者去覆写的,让开发者自己去定义满足什么条件的两个Object是相等的。若Object没有覆写equals(),那么调用equals()就相等于调用==,比较的是两个对象的地址,更严格地说,没有覆写equals()而对其进行调用,是一种错误的行为。

对上面的代码进行修改,覆写Hat的equals()


public class Hat {
    public Hat(String color) {
        this.color = color;
    }

    public String color;

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Hat hat = (Hat) obj;
        return color != null ? color.equals(hat.color) : hat.color == null;
    } 

    @Override
    public int hashCode() {
        return color != null ? color.hashCode() : 0;
    }
}

然后再看看执行结果

 I/hat: 买到了一顶 white 帽子

通过覆写equals(),通过比较Hat的color属性来判断两个Hat对象是否相等,终于成功地买到了一顶white帽子了。

在覆写equals()的同时,我们也覆写了hashCode()方法,至于为什么要覆写hashCode()以及如何去覆写hashCode(),下一篇会详细介绍。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值