Integer.valueOf(42).equals(Long.valueOf(42))
会失败呢?
是否实现equals
必须是“自反,对称,传递,一致”的,但不必合理? :)根据Integer.equals()
文档:
当且仅当参数不为
null
并且是包含与此对象相同int
值的Integer
对象时,结果为真。
换句话说,无论所表示的值如何,Integer
永远不会测试为Long
(或任何其他不是Integer
的东西)等于equals()
。如果您只是想比较原始值,请直接比较它们。
不允许跨类比较的一个好理由是:你该如何做呢?假设您决定实现Integer.equals()
以测试其他对象是否为Number
的实例,并使用other.intValue()
(所有Number
类都支持)来比较值。不幸的结果将是:
Integer.valueOf(42).equals(Long.valueOf(((Integer.MAX_VALUE + 1L) << 1) + 42))
因为Long.intValue()
只是将值强制转换为int
,所以会测试true
(int) ((Integer.MAX_VALUE + 1L) << 1) + 42)
这段代码的结果为42,因为它只考虑了低32位的值。更糟糕的是,如果你在Long.equals()
中使用相同的逻辑(其中它测试所有使用longValue()
的Number
对象),那么equals()
测试将不再对称。
Integer
和 Long
是原始类型 int
和 long
的对象包装类。Integer
中 equals
方法的源代码(这里的 value
是一个 int
原始类型)。public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
以下是 Long
类中 equals
方法的源代码(这里的 value
是一个 long
原始类型)。
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
equals
方法首先检查传入的obj
是否是相应类的实例。如果不是,则equals
跳过对原始value
的检查并返回false
。Integer
永远不会等于Long
(或任何其他不是Integer
的东西)。建议比较原始值。Long theLong = Long.valueOf(42);
Integer theInteger = Integer.valueOf(42);
Long theIntegerInLong = (long) theInteger;
System.out.println(theLong.equals(theIntegerInLong) ? "Equal" : "Unequal");
.equals() 用于在相同继承层次结构中的对象之间进行比较,包括最终超类 Object。虽然 Integer 和 Long 类都继承自 java.lang.Number,但 Number 类显然缺少一个比较 Number 实例值的 .equals() 方法。Integer 和 Long 的唯一共享的 .equals() 方法在 Object 中。Object-to-Object 比较方法不基于数字的值进行评估,因此打印出了看似奇怪的结果。
类 Integer 的文档说: .equals():"当且仅当参数不为 null 并且是包含与此对象相同 int 值的 Integer 对象时,结果为 true。" 它不将 Long 值视为更多的对象。
显然,根据 @David_Wallace 的说法,其他类层次结构在其超类中实现了 .equals()。new ArrayList().equals(new LinkedList()) 返回 true,并且两者都继承自类 java.util.AbstractList,该类具有其自己的 .equals() 实现
Integer
也不能报告自己等于另一个也表示5的新类型实例。采用后一种方法将允许新对象与值为5的Integer
比较相等,但需要添加相对较少的好处所带来的巨大复杂性。BigDecimal
和一个BigRational
类;前者将数字存储为一个带有十进制幂的BigInteger
;后者存储表示约分形式分数的一对BigInteger
值。可以指定所有表示有理数的数字值应通过将它们转换为BigRational
并比较结果来进行比较。由于每个有理数都有唯一的表示,这样定义的比较方法会表现为等价关系。不幸的是,这会非常缓慢。在大多数情况下,将比较对象转换成其他形式会更有意义,但是尝试为任意类型的组合识别最佳公共形式将会很困难。简单地说,不同类型就足以证明这些对象是“不同”的。
Number
类是所有一般数字类型(如Integer
、Long
、Double
等)的父类,还包括BigInteger
和BigDecimal
。因此,它们都必须实现abstract intValue()
方法。这个方法是可用的。Integer
也可以使用它。 - Sotirios Delimanolisdouble
等于BigDecimal
意味着什么。 - Dawood ibn Kareem