a.equals(a)何时返回false?

时间:2014-05-23 17:28:31

标签: java

我想知道哪些是java中的变量不能相等的情况 (使用equals()方法)自己。 我不是在这里讨论对象而是变量本身 (只要代码编译并在调用equals时返回false)。 到目前为止,它发现的唯一情况是:

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

还有其他情况a.equals(a)会返回false吗?

编辑:不允许覆盖equals(),但只要变量{{1},您就可以根据需要修改(强制转换,继承)a最后比较自己。

6 个答案:

答案 0 :(得分:4)

在多线程上下文中它可能会返回false,即使equals实现符合equals contract

class Test {
    public static final A a = new A();

    public static void main(String... args) throws Exception {
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    a.x += 1;
                }
            }
        }.start();
        Thread.sleep(10);

        System.out.println(a.equals(a));  // <---
    }
}

class A {
    int x;

    @Override
    public boolean equals(Object o) {
        return (o instanceof A) && ((A)o).x == x;
    }
}
false

答案 1 :(得分:2)

来自Oracle的Object文档:

public boolean equals(Object obj)

指示某个其他对象是否等于&#34;这个。

equals方法在非null对象引用上实现等价关系:

It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
For any non-null reference value x, x.equals(null) should return false. 

类Object的equals方法实现了对象上最具辨别力的等价关系;也就是说,对于任何非空引用值x和y,当且仅当x和y引用同一对象时,此方法才返回true(x == y的值为true)。

请注意,通常需要在重写此方法时覆盖hashCode方法,以便维护hashCode方法的常规协定,该方法声明相等的对象必须具有相同的哈希代码。

参数:     obj - 要与之比较的参考对象。 返回:     如果此对象与obj参数相同,则返回true;否则返回false。否则就是假的。

回到你的问题并分析文档

a.equals(null);以及ab(分别为AB的对象)的比较时,它是错误的,即a.equals(b)也会返回false。

在其他情况下,这是真的,因为:

It is reflexive: for any non-null reference value x, x.equals(x) should return true.

它清楚地表明:不是对x的空引用(在这种情况下是a):

a.equals(a);将是真的

答案 2 :(得分:1)

我支持khale和Frakcool的回复。除此之外,如果您只是需要另一个案例来做错误的尝试

System.out.println(a.equals((a = new A())));

赋值实际上返回了被赋值的内容,如果它不是调用对象本身,则等于false。

答案 3 :(得分:0)

我认为我们没有办法完成这项工作,因为调用等于自身总是如此。让我解释一下你想要实现的目标。

String foo = "";
bool a = foo.equals(foo); // Here true, the easy one
foo = "some value";
bool b = foo.equals(foo); // Here true, since it's changed and then compared to itself again
bool c = foo.equals(foo="some other value"); // Here should be true again, since the compiler takes first the arguments, makes the assignation, and then makes the equals method execution, so in compiler what happens is:
// 1. Make foo = "some other value"
// 2. Compares foo with foo
// Foo is already changed, so is equals to itself

我没有尝试过自己,但那应该是什么。 如果由于某种原因编译器在行bool c = ...中断,那是因为equals不接收String实例化作为String参数。

答案 4 :(得分:0)

如果正确实施.equals()a.equals(a)永远不会错误。

将表达式传递给equals方法:

a.equals(a = null);

并不比以下更特别:

a.equals(b); or a.equals(null);

您只是比较两个不同的值,将表达式填充到等于调用不会改变它。

答案 5 :(得分:0)

一个非常有趣的案例是你有一个盒装Float的案例,请考虑以下代码:

Float alpha = +0.0f;
Float beta = -0.0f;
boolean equal = alpha.equals(beta);
System.out.println("Equal: " + equal);

boolean equality = alpha.floatValue() == beta.floatValue();
System.out.println("Equality: " + equality);

这将为第一个打印true,为第二个打印false

Float.NaN的情况恰恰相反。