我一直在读一本名为《在Java上用Java思考》的书(我来自C背景(。我遇到了以下两组代码
public class EqualsMethod {
public static void main(String[] args) {
Integer n1 = new Integer(47);
Integer n2 = new Integer(47);
System.out.println(n1.equals(n2));
}
}
//Output: true
我理解这种平等的方法是比较参考。但n1和n2是驻留在堆中两个不同"气泡"中的两个对象。那么为什么他们是平等的呢?
另一个示例代码是
class Value {
int i;
}
public class EqualsMethod2 {
public static void main(String[] args) {
Value v1 = new Value();
Value v2 = new Value();
v1.i = v2.i = 100;
System.out.println(v1.equals(v2));
}
} /* Output:false
}
为什么这是假的?你的深入回答将备受期待。非常感谢。
equals
在自定义类中的行为完全取决于您。如果覆盖它,则决定类中的两个对象何时被视为相等。如果您不重写它,您将获得Object
类的默认实现,它检查两个引用是否引用了同一个对象(即,在您的示例中检查v1==v2
是否为false(。
问题根源:
您没有覆盖eqauals和hashCode,然后JVM为您在Value类的情况下创建的任何对象分配一个新的hashCode
=====================
解决方案:您需要定义衡量价值对象身份的标准,即执行以下
1( 重写equals方法,并指定在实例变量i 的值上检查equals
2( 重写哈希代码并使用实例变量i进行哈希代码比较
==用于对象类中的equals方法,以避免在两个引用指向同一对象时进行不必要的计算,如果不进行计算和比较
公共布尔值等于(Object和Object({
如果(this==anObject({
返回true;
}其他{
// Do the calculation here to check the identity check
}
我理解这种平等的方法是比较参考。
错了。在Object类中,此方法包含引用比较,但Integer有自己的实现,它覆盖了Object提供的实现。
它比较两个整数的值,而不是它们的引用。
Integer
是有价值的类型。因此,与Integer
变量相比,通过比较它们的值来执行。在你的特殊情况下是平等的。
比较通过比较不相等的引用执行的两个对象(引用类型(。
您可以通过在类中重载equals()
方法来编写自己的比较逻辑。
Integer有比较值的方法equals((,而value类没有。它使具有equals的Value类比较"指针",它们是不同的。
如果重写类Value中的equals方法,比较类中的属性i,则它将返回true。例如
所有Wrapper类中的public boolean equals(Object o){
return (this.i == ((Value) o).i) ? true : false;
}
Equals方法在java中默认被覆盖。这就是为什么第一个片段有效。对于您自己的类,您必须提供equals方法的实现。
默认情况下,Java中的equal方法会检查两个Object引用是否相同。您可以@覆盖方法,并执行您想要的操作。所以得到False是正常的,因为这两个Object是不同的。
那么为什么他们是平等的呢?
Integer是一个Object。另一方面,int是一个简单的类型。Integer的equals((方法比较内部的int,因为它覆盖了Object equals(((方法。int的值相同。
为什么这是假的?
您的Value类不会覆盖equal的方法,因此会比较引用,就像您编写v1==v2时一样。在这种情况下,它们是不同的对象,所以这是错误的。
因为您没有覆盖equals方法。如果您不覆盖它,那么它将检查引用是否相等,并相应地返回。
可以参考Integer类中定义的equals()
方法。
System.out.println(n1.equals(n2)) // this prints true because it refers to Integer equals method.
类似地,您将不得不为您的Value类重写它。
class Value {
int i;
@Override
public boolean equals(Object obj) {
boolean returnValue = false;
if (obj != null && obj instanceof Value) {
Value valObj = (Value) obj;
if (this.i == valObj.i) {
returnValue = true;
}
}
return returnValue;
}
}
现在System.out.println(v1.equals(v2));
打印true。
嗨,你对等号和==的理解是完全错误的,或者与实际情况相反。
equals((方法也像==一样检查引用,除非重写equals方法,否则两者之间没有区别。==检查引用是否相等。要更好地理解,请参阅对象类源代码。
public boolean equals(Object obj) {
return (this == obj);
}
为什么它在你的情况下有效?是因为Integer类重写了其中的equals方法。
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
n
}
现在,当您使用自定义类来检查相等性时,它所做的基本上是调用。
v1==v2
它怎么能给你真实的?它们在堆中都有不同的内存位置。如果仍然不清楚,请在代码中设置断点,并在调试模式下运行它。