“一致性相等”的陷阱
作者:网络转载 发布时间:[ 2013/4/10 9:44:01 ] 推荐标签:
关于Object类中的equals()方法与Comparable接口中的compareTo()方法之间有何种关联,之前还真没考虑过。通过java.net看到此文之后,收获了一点儿新知识,希望大家也能如此。
方法equals()与Comparable接口中的compareTo()方法是Java中基本的两个方法之一,然而它们的定义却围绕着"与相等一致"这一有趣的概念。
equals()方法
Java中的equals()方法既明确,又模糊。Java清楚地定义了如何准确地检验一个equals()方法是可用的。一个恰当的equals()方法必须是自反的,对称的,可传递的,一致的,并能处理null引用。
然而equals()方法又是不清晰的。Javadoc说到,该方法指定了其它对象是"等于"这个对象的。注意,"等于"是放在引号中的。此处的关键是,它没有定义如何去判定这种相等性。
·对象的一致性(==)默认是继承自Object类
·对象的整体可观测的状态,例如,若两个对象是相等的,那么在应用的其它部分可以用一个对象去替代另一个对象。
·对象信息中的某些部分,如ID,使得检验对象相等性在逻辑上是有意义的。
compareTo()方法
Comparable接口定义了可比较性的概念。Javadoc指出compareTo()方法"强制设定了每个实现了该接口的类的对象的全部顺序"。
实现了Comparable接口的类有一个天然的排序,这可便于存储,也能在不使用单独的Comparator的情况下,用于像TreeSet和TreeMap这样的集合对象。
该接口的定义明晰,它要求其实现必须确保对称性与传递性,像equals()方法那样。
一致性/非一致性相等
Comparable接口有如下描述:
类C的天然排序意味着要与equals()方法保持一致,只有当且仅当e1.compareTo(e2) == 0与e1.equals(e2)有相同的布尔值。
基本上,这要求由compareTo()定义的相等性与equals()方法定义的相等性具有相同的概念(除去有null的情况)。乍一看,该要求很简单,但实际上它有其复杂性,后面将会讨论到。
当考虑到操作符重载时,这种定义特别有用。若我们假设有一种类Java语言,在这种语言中,==并不表示对象的同一性,而是通过方法去进行比较,大于/小于操作符也是如此,问题是调什么样的方法。在类Java语言中大于/小于天然地要基于compareTo()方法,而==则要调用equals()方法。
// our new Java-like language
if (a < b) return "Less"; // translation ignoring nulls: if (a.compareTo(b) < 0)
if (a > b) return "Greater"; // translation ignoring nulls: if (a.compareTo(b) > 0)
if (a == b) return "Equal"; // translation ignoring nulls: if (a.equals(b))
throw new Exception("Impossible assuming no nulls?");
但如果compareTo()方法不是“一致性相等”,那么上述代码将会抛出异常,因为当a.equals(b)为false时,a.compareTo(b)会返回0。
在集合,如TreeMap,中还会发生其它问题:
// Foo class is "inconsistent with equals"
assert foo1.equals(foo2) == false;
assert foo1.compareTo(foo2) == 0;
TreeMap<Foo, String> map =
map.put(foo1, "a");
map.put(foo2, "b");
当使用equals()方法时,这两个对象不相等,但使用compareTo()时,它们却相等。在这种情况下,该Map的元素个数将为1,而非0。
由于这些“一致性相等”的问题,Javadoc说道“强烈建议(尽管并不要求)天然排序规则要与equals()方法保持一致”。
JDK中的许多类为了符合“一致性相等”这一规范而实现了Comparable接口。这些类包括Byte,Short,Integer,Long,Character和String。
还有些更有趣的类:
BigDecimal--肯定是“非一致性相等”,比如4.00与4.0不一致,但进行比较时,认为它们是一样的。
相关推荐
更新发布
常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11系统性能测试及调优前期准备
2021/4/15 14:41:29国内比较好用的5款测试管理工具
2021/3/25 17:23:31