等价方法中的等价

时间:2014-03-03 21:54:58

标签: java equals

为什么不Integer.valueOf(42).equals(Long.valueOf(42))equals的实现是否必须是“反身的,对称的,传递的,一致的” 但不必合理吗? :)

4 个答案:

答案 0 :(得分:5)

来自Integer.equals()的文档:

  

当且仅当参数不是null并且是包含与此对象相同的Integer值的int对象时,结果才为真。

换句话说,Integer永远不会将equals()测试为Long(或其他任何不是Integer的内容),无论代表什么值。只需比较原始值,如果这就是你所追求的。

不允许跨类别比较的一个很好的理由是:你会怎么做?假设您决定实施Integer.equals()来测试另一个对象是否是Number的实例,并使用other.intValue()(所有Number类都支持)比较值。不幸的结果是

Integer.valueOf(42).equals(Long.valueOf(((Integer.MAX_VALUE + 1L) << 1) + 42))

会测试true,因为Long.intValue()只是将其值转换为int

(int) ((Integer.MAX_VALUE + 1L) << 1) + 42)

评估为42,因为这是低32位的内容。更糟糕的是,如果您对Long.equals()使用了相同的逻辑(测试了所有Number对象使用的longValue()),那么equals()测试将不再是对称的。

答案 1 :(得分:1)

提醒您IntegerLong是原始类型intlong的对象包装类。

以下是Integerequals方法的源代码(value这里是int原语。

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

以下是Longequals方法的源代码(value这里是long原语。

public boolean equals(Object obj) {
    if (obj instanceof Long) {
        return value == ((Long)obj).longValue();
    }
    return false;
}

从源代码开始,equals方法首先检查传入的obj是否是相应类的实例。如果不是,则equals会跳过对原始value的检查并返回false

正如@Ted Hopp建议的那样,Integer永远不会测试等于Long(或其他任何不是Integer)。建议比较原始值。

如果您仍希望在对象包装器设置中执行等效性检查,那么您可能希望扩展Integer(避免溢出)并让Java编译器为您执行一些auto-(un)boxing。有点像...

Long theLong = Long.valueOf(42);
Integer theInteger = Integer.valueOf(42);
Long theIntegerInLong = (long) theInteger;
System.out.println(theLong.equals(theIntegerInLong) ? "Equal" : "Unequal");

答案 2 :(得分:-1)

.equals()用于比较同一继承层次结构中的对象,包括最终的超类Object。虽然类Integer和Long都继承自java.lang.Number,但类Number显然缺少一个比较Number实例值的.equals()方法。 Integer和Long唯一共享的.equals()方法在Object中。对象 - 对象比较方法不会根据数字的值进行评估,因此打印出看似奇怪的结果。

Integer类的文档说: .equals():“当且仅当参数不为null并且是包含与此对象相同的int值的Integer对象时,结果才为真。”它不像对象那样处理Long值。

显然,根据@David_Wallace,其他类层次结构在其超类中实现.equals()。 new ArrayList()。equals(new LinkedList())返回true,并且都从类java.util.AbstractList继承,它有自己的.equals()实现

答案 3 :(得分:-1)

可以在这样的方式中定义包装类之间的相等性测试,即封装相同数值的两个包装器对象将比较相等,而不管底层类型如何。但是,这样做要求要求所有类型的实例可以比较相同才能彼此了解,或者需要定义一种方法,通过该方法,对象可以将自己与尚未发明的其他对象进行比较。采用前一种方法意味着即使新的数字类型能够表示值5,等于5的Integer也不能报告自己等于也代表5的新类型的实例。方法将允许新对象与值{5}的Integer进行比较,但需要增加极大的复杂性才能获得相对较少的好处。

例如,假设一个人定义了BigDecimalBigRational类;前者将数字存储为BigInteger以及十次幂比例因子;后者存储一对BigInteger值,表示缩减形式的分数。可以指定所有表示有理数的数值应通过将它们转换为BigRational并比较结果来进行比较。由于每个有理数都具有唯一的表示,因此这种定义的比较方法将表现为等价关系。不幸的是,它会非常缓慢。在大多数情况下,将比较法转换为其他形式会更有意义,但是尝试识别任意类型组合的最佳常见形式将是困难的。简单地说出不同类型的东西就足以让对象被称为“不同的”#34;