Java: equals and ==

3

假设我们在Java中有一个用户定义的类,有两个实例a和b。是否有可能出现这种情况:a == b,但 a.equals(b) 返回false?

8个回答

8
当然可以!.equals()的实现完全取决于类,所以我可以这样写:
class Foo
    public boolean equals(Object other) {
        return false;
    }
}

现在,无论您传递哪两个实例 - 即使是完全相同的实例两次 - 我总是会说它们不相等。

这种设置特别愚蠢,但它说明了您可以从.equals()中获取同一对象两次的false结果。

请注意,我们在这里讨论的是可能发生的情况,而不是应该发生的情况。任何类都不应该实现一个.equals方法来声明一个对象与其自身不相等。对于受信任的代码,可以合理地假设永远不会发生这种情况。


6
然而,如果遵守了"equals"契约,这是不可能的。 - Louis Wasserman
那是一个重要的观点;我已经编辑了我的答案,包括那个澄清。虽然从技术上讲可能是可行的,但任何真正构建这样东西的人都应该被吊销他们的编程许可证。 - VoteyDisciple

5
如果 a == b,那么 a.equals(b) 应该是 true。如果 a.equals(b),那么 a == b 可能是 true,但不一定。

== 运算符只测试两者是否引用同一个对象。而 equals 执行您实现的逻辑。后者可以被覆盖,前者是语言中的运算符,在 Java 中不能被覆盖。

参考资料

== 运算符和 equals() 方法有什么区别?(带有 hashcode() ???)

来自 java.lang.Object 文档:

equals方法对非null对象引用实现了一种等价关系:
  1. 它是自反的:对于任何非null引用值x,x.equals(x)应该返回true。
  2. 它是对称的:对于任何非null引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)应该返回true。
  3. 它是传递的:对于任何非null引用值x、y和z,如果x.equals(y)返回true并且y.equals(z)返回true,则x.equals(z)应该返回true。
  4. 它是一致的:对于任何非null引用值x和y,只要在对象上的等式比较中未修改任何信息,多次调用x.equals(y)应该始终返回true或始终返回false。
  5. 对于任何非null引用值x,x.equals(null)应该返回false。

4

是的,只需要重载equals来做一些愚蠢的事情。例如:

class Foo {
    @Override
    boolean equals(Object rhs) { return false; }
}

3
很明显,可以编写代码来实现这一点,正如其他答案所指出的那样。但是,这也总是代码中的逻辑错误,因为它违反了equals()函数的隐含普遍契约。一个对象应该始终等于它自己,因此如果(a==b),那么a.equals(b)应该始终返回true。

2

是的,我们可以重载.equals函数来得到期望的输出。但是在任何情况下,==返回true而.equals返回false的情况是不存在的。

class s {
    int a;
}

class dev {
    public static void main(String args[]) {
        s a = new s();
        s b = new s();
        System.out.println(a == b);
        System.out.println(a.equals(b));
    }
}

输出 假 假

0

equals 方法可以被重写,以提供除了典型的 == 方法之外的自定义功能。此外,一些类型如 Strings 在使用 == 方法时不会返回 true。您必须使用 .equals.compareTo(返回 0 时相等)。

这应该提供一些额外的帮助


0
是的,非常容易:
public class Wrong{
    public boolean equals(Object other) 
    {
    return false;
    }
}

当然,这完全违反了实现 .equals() 的正常规则 - 参见Javadocs - 但除了好的判断之外没有什么可以阻止你。

0
package com.stackOverFlow;

import java.util.Date;

public class SampleClass {

public static int  myint = 1;
private SampleClass() {
};

public Integer returnRandom() {
    return myint++;
}

private static SampleClass _sampleClass;

public static SampleClass getInstance() {

    if (_sampleClass == null) {
        _sampleClass = new SampleClass();
    }
    return _sampleClass;
}

@Override
public boolean equals(Object other) {
    if (this.returnRandom().equals(((SampleClass) other).returnRandom())) {
        return true;

    }
    return false;
}

}



package com.stackOverFlow;

public class Run {

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub

    SampleClass a = SampleClass.getInstance();
    SampleClass b = SampleClass.getInstance();
    if(a==b){
        System.out.println("references are same as they are pointing to same object");
        if(!a.equals(b)){
            System.out.println("two random number Instance will never be same");
        }
    }

}

}

你可以通过实际例子理解这个概念。单例模式类会始终返回相同的引用,而你可以重写equals方法以获得不是类变量的内容,例如在两个特定时间从数据库中获取值或一个随机数。希望这能澄清你的问题。


这只是一堵格式不良的代码墙,目前它需要至少两次阅读才能让已经了解Java的人理解。 - Joey
@Joey,我是 SO 的新手,下次会注意的。感谢你指出来。 - ManMohan Vyas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接