[英]Equivalence in equals method
Why not Integer.valueOf(42).equals(Long.valueOf(42))
? 为什么不Integer.valueOf(42).equals(Long.valueOf(42))
? Whether implementation of equals
must be "reflexive, symmetric, transitive, consistent" but don`t have to be reasonable? equals
实现必须是“反身,对称,传递,一致”,但不必合理吗? :) :)
From the docs for Integer.equals()
: 来自Integer.equals()
的文档:
The result is true if and only if the argument is not
null
and is anInteger
object that contains the sameint
value as this object. 当且仅当参数不为null
并且是包含与此对象相同的int
值的Integer
对象时,结果才为真。
In other words, an Integer
will never test as equals()
to a Long
(or anything else that's not an Integer
), regardless of the value being represented. 换句话说,无论表示什么值, Integer
都不会测试为Long
(或其他任何不是Integer
)的equals()
。 Just compare the primitive values if that's what you're after. 只需比较原始值,如果这就是你所追求的。
One good reason for not allowing cross-class comparisons is: how would you do it? 不允许跨类比较的一个很好的理由是:你会怎么做? Suppose you decided to implement Integer.equals()
to test whether the other object was an instance of Number
and compare values using other.intValue()
(which all Number
classes support). 假设您决定实现Integer.equals()
来测试另一个对象是否是Number
的实例,并使用other.intValue()
(所有Number
类支持)比较值。 The unfortunate result would be that 不幸的结果就是那样
Integer.valueOf(42).equals(Long.valueOf(((Integer.MAX_VALUE + 1L) << 1) + 42))
would test true
because Long.intValue()
simply casts its value to an int
and 将测试为true
因为Long.intValue()
只是将其值转换为int
和
(int) ((Integer.MAX_VALUE + 1L) << 1) + 42)
evaluates to 42 because that's what's in the lower 32 bits. 评估为42,因为这是低32位的内容。 What's perhaps even worse, if you used the same logic for Long.equals()
(where it tested all Number
objects used longValue()
), then the equals()
test would no longer be symmetric. 更糟糕的是,如果你对Long.equals()
(使用longValue()
测试了所有Number
对象Long.equals()
使用相同的逻辑,那么equals()
测试将不再是对称的。
A reminder that Integer
and Long
are object wrapper classes of the primitive types int
and long
. 提醒一下, Integer
和Long
是原始类型int
和long
对象包装类。
Here is the source code of the equals
method in Integer
( value
here is an int
primitive). 这是Integer
equals
方法的源代码(这里的value
是一个int
原语)。
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
And here is the source code of the equals
method in Long
( value
here is a long
primitive). 这里是Long
equals
方法的源代码(这里的value
是一个long
原语)。
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
From the source, the equals
method firstly checks if the passed-in obj
is an instance of the corresponding class. 从源代码开始, equals
方法首先检查传入的obj
是否是相应类的实例。 If it isn't, equals
skips the check on the primitive value
and returns false
. 如果不是,则equals
跳过对原始value
的检查并返回false
。
So as @Ted Hopp suggested, an Integer
will never test as equal to a Long
(or anything else that's not an Integer
). 因此,正如@Ted Hopp建议的那样, Integer
永远不会测试等于Long
(或其他任何不是Integer
)。 Comparing primitive values is recommended. 建议比较原始值。
If you nonetheless would like to carry out the equivalence check in the object wrapper setting, then you may wish to widen your Integer (avoiding an overflow) and let the Java compiler do some auto-(un)boxing for you. 如果您仍希望在对象包装器设置中执行等效检查,那么您可能希望扩展整数(避免溢出)并让Java编译器为您执行一些自动(非)装箱 。 Something like... 就像是...
Long theLong = Long.valueOf(42);
Integer theInteger = Integer.valueOf(42);
Long theIntegerInLong = (long) theInteger;
System.out.println(theLong.equals(theIntegerInLong) ? "Equal" : "Unequal");
.equals() is for comparisons between objects in the same inheritance hierarchy, up to and including the ultimate superclass Object. .equals()用于比较同一继承层次结构中的对象,包括最终的超类Object。 While classes Integer and Long both inherit from java.lang.Number, class Number is apparently missing an .equals() method that compares a Number instance value. 虽然类Integer和Long都继承自java.lang.Number,但类Number显然缺少一个比较Number实例值的.equals()方法。 Integer and Long's only shared .equals() method is in Object. Integer和Long唯一共享的.equals()方法在Object中。 The Object-to-Object comparison method does not evaluate based on the values of the numbers, hence the seemingly strange result printed. 对象 - 对象比较方法不基于数字的值进行评估,因此打印出看似奇怪的结果。
The documentation for class Integer says: .equals(): "The result is true if and only if the argument is not null and is an Integer object that contains the same int value as this object." 类Integer的文档说:.equals():“当且仅当参数不为null并且是包含与此对象相同的int值的Integer对象时,结果才为真。” It doesn't handle Long values as more than Objects. 它不像对象那样处理Long值。
Apparently as per @David_Wallace, other class hierarchies implement .equals() in their superclass. 显然,根据@David_Wallace,其他类层次结构在其超类中实现.equals()。 new ArrayList().equals(new LinkedList()) returns true, and both inherit from class java.util.AbstractList which has its own implementation of .equals() new ArrayList()。equals(new LinkedList())返回true,并且都从类java.util.AbstractList继承,它有自己的.equals()实现
It would have been possible to define the equality tests among wrapper classes in such a fashion that two wrapper objects that encapsulated the same numerical value would compare equal, regardless of the underlying type. 可以在这样的方式中定义包装类之间的相等性测试,即封装相同数值的两个包装器对象将比较相等,而不管底层类型如何。 Doing so, however, requires either having all types whose instances may compare equal know about each other, or else requires defining a means via which objects will be able to compare themselves to other objects which haven't even been invented yet. 但是,这样做要求要求所有类型的实例可以比较彼此相同,或者需要定义一种方法,通过该方法,对象可以将自己与尚未发明的其他对象进行比较。 Taking the former approach would mean that even if a new numeric type was capable of representing the value 5, an Integer
which equaled 5 could not report itself equal to an instance of the new type which also represented 5. Taking the latter approach would allow the new object to compare equal to an Integer
with value 5, but would require adding enormous complexity for comparatively little benefit. 采用前一种方法意味着即使新的数字类型能够表示值5,等于5的Integer
也不能报告自己等于也表示为5的新类型的实例。采用后一种方法将允许要比较的新对象等于值为5的Integer
,但是需要增加极大的复杂性才能获得相对较少的好处。
Suppose, for example, that one has defined both a BigDecimal
and a BigRational
class; 例如,假设一个人定义了BigDecimal
和BigRational
类; the former stores numbers as a BigInteger
along with a power-of-ten scaling factor; 前者将数字存储为BigInteger
同时存储十个幂的比例因子; the latter stores a pair of BigInteger
values which represent a reduced-form fraction. 后者存储一对BigInteger
值,表示缩减形式的分数。 One could specify that all numeric values which represent rational numbers should be compared by converting them to BigRational
and comparing the results. 可以指定表示有理数的所有数值都应该通过将它们转换为BigRational
并比较结果来进行比较。 Since every rational number would have a unique representation, such a defined method of comparison would behave as an equivalence relation. 由于每个有理数都具有唯一的表示,因此这种定义的比较方法将表现为等价关系。 Unfortunately, it would be horrendously slow. 不幸的是,它会非常缓慢。 In most cases, it would make more sense to convert comparands into some other form, but trying to identify the best common form for arbitrarily combinations of types would be difficult. 在大多数情况下,将比较法转换为其他形式会更有意义,但是尝试识别任意类型组合的最佳常见形式将是困难的。 It's much easier to simply say being of different types is sufficient justification for the objects to be called "different". 简单地说,不同类型的对象被称为“不同”的充分理由要容易得多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.