32

I'm still pretty fresh to all this, but I'm working on attaining my OCAJP certification (Java). I remembered reading previously that the .equals method could be overridden when I came to this question:

Question from Enthuware prep materials:

Now these questions have been pretty evil as far as I'm concerned. Twisting every little thing you think you know to force you to learn all the minutiae. Now I had guessed E, but I didn't think D was correct. I mean 99.9% of the time, of course, but I thought it was a trick question based on the wording.

This got me thinking, is that true? I mean, if I get the question on the exam, I know how to answer it now, but in the deep dark abyss of overriding madness, is it possible to create a situation where a.equals(a) returns false? I feel like this would make Aristotle angry...

Steve the Maker
  • 611
  • 6
  • 11
  • 1
    I _don't think this is evil_ at all - it's just asking about what one should expect about base classes of the language. It would be _evil_ to ask if a custom class could override `equals` so that `a.equals(a)` is `false`, as one _can technically_ do that but _shouldn't_ as you'd be violating `equals` contact. – mgarciaisaia Aug 24 '15 at 14:18
  • I mean, don't start thinking _this_ question is _evil_, because with that mindset you'll be too biased to correctly think about what you know during the exam. – mgarciaisaia Aug 24 '15 at 14:19
  • I believe the issue is that it didn't specify that they were *the* primitive wrapper classes as opposed to any random primitive wrapper class. – Captain Man Aug 24 '15 at 15:54
  • possible duplicate of [What issues should be considered when overriding equals and hashCode in Java?](http://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and-hashcode-in-java) – Raedwald Aug 27 '15 at 08:53

5 Answers5

47

Note that a. b and c are instances of primitive wrapper classes (such as Integer, Double, etc...). These classes are final and cannot be extended, so you can't override their equals implementation.

Therefore a.equals(a) will always return true, since those classes implement equals properly.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • Okay, so the tricky bit of this question was the wrapper classes portion -which I must have missed. Thanks! But as far as turning the world upside-down with .equals, that's still possible in non-final classes? – Steve the Maker Aug 24 '15 at 05:50
  • You are probably referring to other classes, not the wrapper of primitives. In this case you can override equals in any way you want to. – Yair Zaslavsky Aug 24 '15 at 05:51
  • 9
    @StevetheMaker You can always extend a non-final class and override equals with `public boolean equals(Object other) {return false;}`. That won't make any sense, but you can do it. – Eran Aug 24 '15 at 05:51
  • @Eran That makes sense. The prep materials are, again, truly evil. There's literally a dozen or so questions where they say, basically that, in the description. Something like... You're wrong because of this... nobody will ever actually code like this if they have half a brain, but if they did, you'd be wrong... Hence my confusion. – Steve the Maker Aug 24 '15 at 05:56
  • 10
    There is one caveat that the question might aim at: For a `double` value, there may indeed be the case that `d != d` - namely when its value is `Double.NaN`. But still, for `Double d = Double.valueOf(Double.NaN)`, the `equals` method will return `true` for `d.equals(d)`. – Marco13 Aug 24 '15 at 09:13
  • Except when you use Reflection to change the internal value in another thread while the comparison takes place. So if you want to be really pedantic **Option D is FALSE** (see my answer for a contrived example) – Falco Aug 24 '15 at 12:25
  • Note that when you do this you are breaking the **reflexive contract (`a.equals(a) should be true`)** of the equals method. Which may cause unknown problems. – Codebender Aug 24 '15 at 12:35
  • @Marco13 is right. `Double.equals` doesn't even behave like `x==y` on the corresponding native values. `Double.equals` doesn't actually compare the internal values using `obj.value==value` but rather `doubleToLongBits(((Double)obj).value) == doubleToLongBits(value)`. In other words, it is the bit representations that need to match, not equality by the usual float conventions. Presumably this is done to fulfill the reflexive contract. – nitro2k01 Aug 24 '15 at 16:20
21

Since equals(...) is not a final method of Object, yes, it is very well be possible in a different situation.

@Override
public boolean equals(Object obj) {
    return false;
}

This question, however, specifically says that these are primitive wrappers (e.g. Integer, Boolean, etc.) and since these classes are final, you cannot extend them, thus a.equals(a) will always return true.

Gergely Kőrössy
  • 5,620
  • 3
  • 28
  • 44
7

Integer a.equals( a ) can return false

But you have to be really evil and use reflections and Multithreading:

If you run this code, there is a chance that a racing condition can change the internal Value of myInt while the comparision takes place. If you want to simulate this condition, just set a breakpoint inside of Integer.intValue() run the code in debug and hit continue. This will create a delay which creates the race condition artificially and the console will return false.

class IntegerEqualsTest
{
    public static void main( final String[] args )
    {
        final Integer myInt = new Integer( 420 );

        new Thread() {
            public void run() {
                try {
                    final Field f = Integer.class.getDeclaredField( "value" );
                    f.setAccessible( true );
                    f.setInt( myInt, 100 );
                } catch( final Exception e ) {}
            }; }.start();

        System.out.println( myInt.equals( myInt ) );
    }
}
Falco
  • 3,287
  • 23
  • 26
  • 3
    While clever and evil, this piece of code does not exploit overriding methods (wording of the original question) or any mechanism specific to `.equals`. Writing thread unsafe code can trigger a variety of problems, not just this, as can holding a stick of uranium-235 near the RAM in the computer. :) – nitro2k01 Aug 24 '15 at 15:12
  • @nitro2k01 I wouldn't even call this thread unsafe, since setting an integer value is usually an atomic operation, so this code is only semantically thread unsafe, not on a low language level. – Falco Aug 24 '15 at 15:16
  • 1
    Well, technically thread safe or not, the idea that you can go and change a value from another thread brings uncertainty to _exactly_ _every_ question, and does nothing to characterize the behavior of the equals method per se. – nitro2k01 Aug 24 '15 at 16:10
  • Another problem here is that we use reflection to make an officially immutable class mutable again. Don't do this. – Paŭlo Ebermann Aug 24 '15 at 16:15
  • @PaŭloEbermann This is not something I would ever do in any productive code. It is an answer to the pedantic question if equals can ever return false for the same reference. And it is good to know this, because many WebFrameworks use reflection to access a lot of classes and attributes - and you always have multithreading, so this answer shows, how important proper synchronization is... becuase without no guarantees whatsoever will hold in your code. – Falco Aug 25 '15 at 08:20
6

The other answers have already answered your question - no, this is not possible with the Java's primitive wrapper classes.

I'll try to address the "question behind the question": Is this possible with other classes?

[...] in the deep dark abyss of overriding madness, is it possible to create a situation where a.equals(a) returns false? I feel like this would make Aristotle angry...

This is actually a good question, and the answer is: Yes, it is possible to create such a situation, and yes, it would make Aristotle angry. Actually, I don't know if it would make Aristotle angry, not having known him, but it will certainly cause a lot of grief for whoever has to work with the code.

The thing is: There is a contract associated with Object.equals():

The equals method implements an equivalence relation on non-null object references:

[...]

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

Javadocs for Object.equals

Yes, when creating your own class, you can violate this contract. There is (unfortunately) nothing in the compiler or runtime stopping you.

However, a lot of code relies on this contract, so if you violate it, any code that uses equals will probably fail in mysterious ways.

One example: Java's own Collection classes (java.util.Collection and friends) rely on equals. If an instance of a class that does not correctly implement equals is put into a collection, weird things happen, such as the collection sometimes containing the instance and sometimes not.

sleske
  • 81,358
  • 34
  • 189
  • 227
  • 1
    A relation can be symmetric and anti-reflexive. (Of course the javadoc you link to also specifies reflexivity) – Taemyr Aug 24 '15 at 08:44
  • 1
    @Taemyr: Yes, a _relation_ can be anti-reflexive, but an _equivalence relation_ is reflexive by definition. Small but important distinction :-). – sleske Aug 24 '15 at 09:31
  • Sure, that still leaves the question of why the one property you chose to include is symmetry. - Considering that the question is explicitly about reflexivity. – Taemyr Aug 24 '15 at 09:53
1

You can take a look at the implementations of all the primitive wrappers , i.e: Integer, Boolean, Character etc... you will see that the implementation is correct.
The reason is that with equals, once of the checks being done is to check reference equality, and x.equals(x) as the both object and the argument are the same object.

Yair Zaslavsky
  • 4,091
  • 4
  • 20
  • 27