麻省理工Java软件构造 等价性

原链接

等价关系

等价性,其实我们一直有接触。

在集合论中,我们其实学过等价的具体定义:

等价关系:等价是指对于关系E ⊆ T x T ,它满足:

  • 自反性: E(t,t) ∀ t ∈ T
  • 对称性: E(t,u) ⇒ E(u,t)
  • 传递性: E(t,u) ∧ E(u,v) ⇒ E(t,v)

JAVA中的“==”与“equals()"

这两者是不同的。

“==” 判断两个对象是否指向了存储空间中的同一个地址,而“equals()"判断两个对象的值是否相等。

当然,对于基本数据类型(如int,不是一个对象), “==”就表示值是否相等

不可变类型(immutable)的相等

Object类其实已经提供了equals()方法了,不过效果和 == 完全一样,

public class Object {
    ...
    public boolean equals(Object that) {
        return this == that;
    }
}

所以,对于每一个新创建的类,我们都需要重写该方法。注意,重写需要加上@Override,否则,只是对该方法进行了参数不同的重载(overload)

public class Duration {
    private final int mins;
    private final int secs;
    // Rep invariant:
    //    mins >= 0, secs >= 0
    // Abstraction function:
    //    AF(min, secs) = the span of time of mins minutes and secs seconds

    /** Make a duration lasting for m minutes and s seconds. */
    public Duration(int m, int s) {
        mins = m; secs = s;
    }
    /** @return length of this duration in seconds */
    public long getLength() {
        return (long)mins*60 + secs;
    }
}

对上面这个类进行重写equals():

@Override
public boolean equals(Object that) {
    return that instanceof Duration && this.sameValue((Duration)that);
}

// returns true iff this and that represent the same abstract value
private boolean sameValue(Duration that) {
    return this.getLength() == that.getLength();
}

这里的重写,先判断是否是Duration类型的对象,然后判断值是否相等。

注意,重写equals(),需要遵循这几个规定:

  • equals 必须定义一个等价关系。即一个满足自反性、对称性和传递性关系。
  • equals 必须是确定的。即连续重复的进行相等操作,结果应该相同。
  • 对于不是null的索引x, x.equals(null) 应该返回false。
  • 如果两个对象使用 equals 操作后结果为真,那么它们各自的hashCode 操作的结果也应该相同。

其中,第四个原则是接下来讨论的重点。

也就是说,我们在重写equals()的同时,还需要重写hashCode(),需要让两个相等的对象返回相同的哈希值。

@Override
public int hashCode() {
    return (int) getLength();
}

可变类型(mutable)的相等

我们来定义两种不同的相等:

  • 观察相等(observational equality):两个引用所指向的对象在当前相等,所有值都相同。但无法保证,在改变了其中的一个对象的值之后,这两个对象是否还能保持相同
  • 行为相等(behavioral equality):两个引用所指向的对象始终相等,即使只改变其中的一个值,另一个的值也会跟着变化,从而保持始终相等

简单来说,观察相等,就是观察此时此刻两个引用的值是否相等,而行为相等,就是看这两个引用是否指向同一个对象,也就是我们之前说过的alias

比如,在下图中,d2和o2就是行为相等,因为两个引用指向了同一个对象,所以它们始终都会相等
在这里插入图片描述

需要注意的是,在JAVA中,对于可变数据类型,通常采用的是观察相等,比如判断两个List是否相等,看的是它们所包含的对象及顺序是否相等。

不过需要注意的是,可变类型需要采用行为相等

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值