Are there any scenarios where `==` is true and `equals` is false?

In the standard Java API, are there any scripts in which == will return true , but equals will return false . Theoretically, this could be written into a custom class rather trivially, like this

 class A { public boolean equals(Object o) { return this != o; } } 

Are there really any examples where b == c true returned for some objects b and c , but b.equals(c) returns false ? Also, would there be any possible benefit to such behavior?

+6
source share
4 answers

Not *.

The contract for equals has 5 rules , and the first covers this case:

The equals method implements an equivalence relation for non-zero object references:

  • This is reflective: for any non-zero reference value x, x.equals (x) should return true.
  • It is symmetrical: for any non-empty reference values โ€‹โ€‹x and y x.equals (y) should return true if and only if y.equals (x) returns true.
  • This is transitive: for any non-empty 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.
  • This is consistent: for any non-empty reference values โ€‹โ€‹x and y, several calls to x.equals (y) successively return true or successively return false if the information used in equal comparisons with objects does not change.
  • For any non-zero reference x, x.equals (NULL) should return false.

Any object in the standard Java library that violates reflexivity will be an error, and if you find such an object in the API, notify Oracle.

* Less can be said about third-party libraries. Developers make mistakes or donโ€™t know about equals contract. As a rule, this also qualifies as a bug in a third-party library, but YMMV.

+5
source

In the standard Java API, are there any scripts in which == will return true , but equals will return false [?]

Not as far as I know, and I'm sure that any examples you discover will be considered errors.

In particular, if x and y are links, such as x == y , then it should be such that x.equals(y) is evaluated with the same result as x.equals(x) . The contract on Object.equals() (in its documents) says this, in particular:

The equals method implements an equivalence relation to a nonzero value of an object reference:

  • This is reflective: for any non-zero reference value x , x.equals(x) should return <T21>.

Thus, any redefinition of Object.equals() semantically incorrect if it produces the result for any x and y references that x == y && !x.equals(y) true.

+1
source

In the standard Java API, are there any scripts in which == will return true , but equals will return false .

I'm not sure if this is exactly what you mean, but equals implementations should not be thread safe and should not explicitly check if the argument is the same instance as this . Therefore, in principle, it is possible for foo.equals(foo) to return false if foo simultaneously changing in another thread.

I doubt that any JDK class is explicitly documented as not including this check; rather, considering the implementation detail, except for classes where this is the only check. But I managed to get sb.equals(sb) to at least raise an ArrayIndexOutOfBoundsException when sb is a StringBuilder to which another thread repeatedly adds elements; therefore, if you are particularly unlucky in your time, it should also return false .

Also, would there be any possible benefit to such behavior?

I really donโ€™t think so. The goal of equals is to support things like Set and Map and Assert.assertEquals etc. There are many precedents that donโ€™t use equals at all, but I canโ€™t imagine a scary piece of code that uses equals , but wants it not to represent a form of equality that satisfies an identity.

However, of course, for the non-scary part of the code, there is an error that accidentally causes this. For example, I mentioned in a comment above that java.util.Date and java.sql.Timestamp have a design error (now officially codified) in which date.equals(ts) can be true , but ts.equals(date) is false . Someone trying to solve this problem might modify java.util.Date to enable if (that.getClass() == Date.class) ; but then this will lead to a non-reflexive implementation of equals in any subclass that does not explicitly override the parent implementation. (Of course, I would not expect such an error in the JDK.)

Writing equals correctly in the face of inheritance is actually quite complicated, but, fortunately, there is a well-known solution that tracks all the difficulties: http://www.artima.com/lejava/articles/equality.html .

+1
source

As you pointed out, it is possible to implement equals in such a way that x == x , but !x.equals(x) . However, this violates the documented equals behavior , which states that this property must be satisfied for any valid implementation. This way, you wonโ€™t find any examples in the standard Java API that do this (unless an error appears somewhere), and you will find a lot of code that implicitly or explicitly relies on equals does not behave this way.

0
source

Source: https://habr.com/ru/post/1014238/


All Articles